1. 程式人生 > >最大報銷額 ~01背包

最大報銷額 ~01背包

整數 print 小數點後兩位 %d nbsp 文字 else printf 筆經

現有一筆經費可以報銷一定額度的發票。允許報銷的發票類型包括買圖書(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


題意顯然 是求最大報銷額度 顯然是01背包 最大價值
這題有個坑點就是存在小數,輸入的數據都是小數點後兩位,所以我們擴大100倍轉化為整數類型,便於處理數據。

 1 #include<iostream>
 2 #include<stdio.h>
 3 #include<string.h>
 4
using namespace std; 5 #define maxn 3000010 6 int dp[maxn],a[maxn]; 7 int main() { 8 int cnt,n; 9 double v; 10 while(scanf("%lf%d",&v,&n)!=EOF){ 11 if (n==0 ) break; 12 cnt=0; 13 int maxv=(int)(v*100); 14 for(int i=1;i<=n;i++) 15 { 16 int
num; 17 char b; 18 double va=0,vb=0,vc=0; 19 scanf("%d",&num); 20 int flag=1; 21 while(num--){ 22 scanf(" %c:%lf",&b,&v); 23 if (b==A) va+=v; 24 else if (b==B) vb+=v; 25 else if (b==C) vc+=v; 26 else flag=0; 27 } 28 if (flag && va<=600 && vb<=600 && vc<=600 && va+vb+vc<=1000) a[++cnt]=(int)((va+vb+vc)*100); 29 } 30 memset(dp,0,sizeof(dp)); 31 for(int i=1;i<=cnt;i++) 32 for(int j=maxv;j>=a[i];j--) 33 dp[j] = max(dp[j],dp[j-a[i]]+a[i]); 34 35 printf("%.2lf\n",(dp[maxv])/100.0 ); 36 } 37 return 0; 38 }

最大報銷額 ~01背包