题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1864
注意事项:
在这里所有输入的价格都是两位小数(题目没说,看论坛才知道的)。
这里单项价格不能超过600,可能有这样的情况:2 A:300 A:400,非常坑(也是看论坛才知道的)。
因为最多有30张发票,假设最多都是1000,那么数组就要开到30*1000*100+5这么大。
因为下标不可以是小数,那么可以把价格乘以100,把它变成整数。
代码:
#include<iostream> #include<cstring> #include<algorithm> #include<queue> #include<map> #include<stack> #include<cmath> #include<vector> #include<set> #include<cstdio> #include<string> #include<deque> using namespace std; typedef long long LL; #define eps 1e-8 #define INF 0x3f3f3f3f #define maxn 3000005 /*struct point{ int u,w; }; bool operator <(const point &s1,const point &s2) { if(s1.w!=s2.w) return s1.w>s2.w; else return s1.u>s2.u; }*/ int n,m,k,t; double limit,dp[maxn]; int value[50]; double A,B,C;//用来记录一张发票里面ABC的总价格 bool jug(char c,double cost)//判断这张发票是否可以报销 { if(c=='A') A+=cost; else if(c=='B') B+=cost; else if(c=='C') C+=cost; else return false; if(cost>600||A>600||B>600||C>600) return false; return true; } int main() { while(scanf("%lf%d",&limit,&n)) { limit*=100; if(n==0) break; fill(value,value+40,INF); int num; double sum,cost; char c; for(int i=1;i<=n;i++) { scanf("%d",&num); sum=0; A=0,B=0,C=0; while(num--) { getchar(); scanf("%c:%lf",&c,&cost); if(sum!=INF&&jug(c,cost)) { sum+=cost; if(sum>1000) sum=INF;//如果不行就设为无穷大,表示无法报销 } else sum=INF; } if(sum!=INF) { value[i]=sum*100; } } memset(dp,0,sizeof(dp)); for(int i=1;i<=n;i++)//一维的01背包 { if(value[i]==INF) continue; for(int j=(int)limit;j>=value[i];j--) dp[j]=max(dp[j],dp[j-value[i]]+value[i]); } printf("%.2lf ",dp[(int)limit]/100); } return 0; }