http://acm.hdu.edu.cn/showproblem.php?pid=1864
普通DP和背包的结合
dp[i]表示报销i张发票的最大额数
dp[j]=max(dp[j],dp[j-1]+a[i]);就是说可以,报销J个发票所得到的最大经费,可以第j个是报销的,
也可以是第j个不报销而最大经费是由前j-1个发票加上另外第i个发票的报销数额。。
#include <stdio.h>
#include <string.h>
#define MAX 100550
double dp[MAX],a[MAX];
double max(double a,double b)
{
if(a-b>0.0000001)
return a;
return b;
}
int main()
{
int t,n,i,j,num,flag,k;
double res;
double total;
double A,B,C;
char ch1;
double p;
//freopen("a.txt","r",stdin);
while( scanf("%lf%d",&total,&t) )
{
if(t==0)break;
memset(dp,0,sizeof(dp));
memset(a,0,sizeof(a));
num = 0;
for(k=0;k<t;k++)
{
A = B = C = 0.0;
flag = 1;
scanf("%d",&n);
for(i=0;i<n;i++)
{
scanf(" %c:%lf",&ch1,&p);
if(ch1 != 'A' && ch1 != 'B' && ch1 != 'C' || p > 600.00)
{
flag = 0;
continue;
}
if(ch1 == 'A')
A += p;
else if(ch1 == 'B')
B += p;
else if(ch1 == 'C')
C += p;
}
if(flag && A + B + C <= 1000 && A <= 600 && B <= 600 && C <= 600 )
a[num++] = A + B + C;
}
for(i=0;i<num;i++)
{
for(j=num;j>=1;j--)
{
if(j==1 || dp[j-1]>0 && dp[j-1]+a[i]<=total)
dp[j] = max(dp[j],dp[j-1]+a[i]);
}
}
res = dp[1];
for(i=1;i<=num;i++)
{
if(res<dp[i] )
res = dp[i];
}
printf("%.2lf\n",res);
}
return 0;
}