#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int maxn=100;
int n;
double q;
int dp[3000050];
int f[maxn];
double maxsum;
int m;
char a;
double b;
int main()
{
int ff=1;
while(scanf("%lf%d",&q,&n)!=EOF)
{
int ss=(int)(q*100);
int k=0;
maxsum=0;
if(n==0)
break;
memset(f,0,sizeof(f));
memset(dp,0,sizeof(dp));
for(int i=0;i<n;i++)
{
scanf("%d",&m);
int sum1=0,sum2=0,sum3=0;
ff=1;
for(int j=0;j<m;j++)
{
scanf(" %c:%lf",&a,&b);
int v=int(b*100);
if(a=='A'&&sum1+v<=60000)
sum1+=v;
else if(a=='B'&&sum2+v<=60000)
sum2+=v;
else if(a=='C'&&sum3+v<=60000)
sum3+=v;
else
ff=0;
}
if(sum1+sum2+sum3<=100000&&ff&&sum1<=60000&&sum2<=60000&&sum3<=60000)
f[k++]=sum1+sum2+sum3;
}
for(int i=0;i<k;i++)
{
for(int j=ss;j>=f[i];j--)
dp[j]=max(dp[j],dp[j-f[i]]+f[i]);
}
maxsum=dp[ss]/100.0;
printf("%.2lf\n",maxsum);
}
return 0;
}
这个题目的话还是不错的简单DP,容易想到是用的01背包的方法,但是要思考仔细和01背包略微的区别,这个是把容量和价值都定义为一个意义的。
然后就是要注意一张发票上面可能同一种物品比如A可能贴了N次(不止一次),不然在构造f函数的会想错了,这样就容易WA了。