题目:http://acm.hdu.edu.cn/showproblem.php?pid=1864
最大报销额
01背包,对于每张发票要么报销,要么不报销,张数为背包。注意处理每张发票的合法性。
经验:理解DP的状态,这里的状态是张数。
#include <cstdio>
#include <cstring>
#define clr(a,b) memset(a,b,sizeof(a))
double number[40],dp[40];
int n;
struct st
{
double a,b,c,sum;
bool flag;
};
void init()
{
int m;
struct st temp;
double num;
char ch;
scanf("%d",&m);
temp.a = temp.b = temp.c = temp.sum = 0.0;
temp.flag = true;
for(int i=1; i<=m; i++)
{
scanf(" %c:%lf",&ch,&num);
if(ch == 'A') {temp.a +=num; temp.sum+=temp.a;}
else if(ch == 'B') {temp.b +=num; temp.sum+=temp.b;}
else if(ch == 'C') {temp.c +=num; temp.sum+=temp.c;}
else temp.flag = false;
}
if(temp.a >600 || temp.b>600 || temp.c >600 || temp.sum>1000) temp.flag = false;
if(temp.flag)
{
n++;
number[n]= temp.a + temp.b + temp.c;
}
}
int main()
{
double Q;
int N;
while(scanf("%lf%d",&Q,&N) != EOF)
{
if(N==0)
break;
n=0;
for(int i=1; i<=N; i++)
init();
clr(dp,0);
for(int i=1; i<=n; i++)
for(int j=n; j>=1; j--)
dp[j] = dp[j] > dp[j-1]+number[i] ? dp[j] : dp[j-1]+number[i];
double max = 0;
for(int i=1; i<=n; i++)
if(dp[i] > max && dp[i]<=Q)
max = dp[i];
printf("%.2lf\n",max);
}
}