HDU 1684 最大報銷額

Problem Description
現有一筆經費可以報銷一定額度的發票。允許報銷的發票類型包括買圖書(A類)、文具(B類)、差旅(C類),要求每張發票的總額不得超過1000元,每張發票上,單項物品的價值不得超過600元。現請你編寫程序,在給出的一堆發票中找出可以報銷的、不超過給定額度的最大報銷額。
 

Input
測試輸入包含若干測試用例。每個測試用例的第1行包含兩個正數 Q 和 N,其中 Q 是給定的報銷額度,N(<=30)是發票張數。隨後是 N 行輸入,每行的格式爲:
m Type_1:price_1 Type_2:price_2 ... Type_m:price_m
其中正整數 m 是這張發票上所開物品的件數,Type_i 和 price_i 是第 i 項物品的種類和價值。物品種類用一個大寫英文字母表示。當N爲0時,全部輸入結束,相應的結果不要輸出。
 

Output
對每個測試用例輸出1行,即可以報銷的最大數額,精確到小數點後2位。
 

Sample Input
200.00 3 2 A:23.50 B:100.00 1 C:650.00 3 A:59.99 A:120.00 X:10.00 1200.00 2 2 B:600.00 A:400.00 1 C:200.50 1200.50 3 2 B:600.00 A:400.00 1 C:200.50 1 A:100.00 100.00 0
 

Sample Output
123.50 1000.00 1200.50
 

0—1揹包,把每張發票當一個物品, 其中,發票中有單項大於600的或者總額大於1000的,這張發票扔掉不要,也就是不加入物品的行列。整理出每張發票的總額,作爲這件物品的價值也作爲容量(相當於物品的體積),放到容量爲q的揹包中,這就是標準的0—1揹包了;

轉移方程:f[j]=max(f[j],f[j-1]+v[i]);

代碼:

#include <stdio.h>
#include <string.h>
int max(int a,int b)
{
       if(a>b)
              return a;
       return b;
}
int dp[3000010];
int main()
{
	int n,i,j,m,flag,len;
	double q,val;
	int w[35];
	int w1[3];
	char ch;
	while (scanf("%lf%d",&q,&n)!=EOF&&n)
	{
		memset(dp,0,sizeof(dp));
		len = 0;
		for (i=0;i<n;i++)
		{
			scanf("%d",&m);
			flag = 1;
			for(j=0;j<3;j++)
				w1[j] = 0;
			j = 0;
			while (m--)
			{
				getchar();
				scanf("%c:%lf",&ch,&val);
				if(ch>='A'&&ch<='C')
				{
					j = ch-'A';
					w1[j]+=(int)(val*100);
				}
				/*不可報銷條件*/
				if(w1[j]>60000||w1[0]+w1[1]+w1[2]>100000||ch!='A'&&ch!='B'&&ch!='C')
					flag = 0;
			}
			if (flag)
				w[len++] = w1[0]+w1[1]+w1[2];
		}
		for (i=0;i<len;i++)
		{
			for (j=(int)(q*100);j>=w[i];j--)
				dp[j] = max(dp[j],dp[j-w[i]]+w[i]);
		}
		printf("%.2lf\n",(double)(dp[(int)(q*100)]/100.0));
	}
	return 0;
}


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章