题目:hdu1864
题意:现有一笔经费可以报销一定额度的发票。允许报销的发票类型包括买图书(A类)、文具(B类)、差旅(C类),要求每张发票的总额不得超过1000元,每张发票上,单项物品的价值不得超过600元。现请你编写程序,在给出的一堆发票中找出可以报销的、不超过给定额度的最大报销额。
解答:普通的01背包问题。需要注意的是输入!
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
using namespace std;
double W;
int n;
const int MAXN = 35;
const int maxn = 3000100;
int dp[maxn];
int main()
{
while(scanf("%lf%d",&W,&n)&&n)
{
int cnt = 0;
int w = (int)(W*100);
int v[MAXN];
memset(dp,0,sizeof(dp));
for(int i = 1;i <= n;i++)
{
int t;
scanf("%d",&t);
double a;
int ok = 0;
double sum = 0,sa = 0,sb = 0,sc = 0;
char s,s1;
for(int j = 1;j <= t;j++)
{
//scanf("%c%c",&s,&s1);
scanf(" %c:%lf",&s,&a);
if(s != 'A' && s != 'B' && s != 'C')
ok = 1;
else
{
if(s == 'A')
sa += a;
else if(s == 'B')
sb += a;
else if(s == 'C')
sc += a;
}
if(sa > 600 || sb > 600 || sc > 600)
ok = 1;
sum += a;
}
//cout << ok << endl << sum << endl;
if(!ok && sum <= 1000)
v[cnt++] = (int)(sum * 100);
}
//cout << w << endl;
// dp[0] = 0;
for(int i = 0;i < cnt;i++)
for(int j = w;j >= v[i];j--)
dp[j] = max(dp[j],dp[j-v[i]]+v[i]);
double ans = (double)dp[w]/100;
printf("%.2f\n",ans);
}
return 0;
}