题目链接:HDU 1864 最大报销额
01背包。
把张数当成背包,状态转移方程:f[j]=max(f[j],f[j-1]+v[i]),f[j]表示把j张装进背包的最大报销额。
这题这么做还是有点问题,比如这组数据:
100.00 5
1 A:5
1 B:20
1 C:24
1 A:30
1 A:60
f[3]为114,f[2]为90,f[3]超过了100.00,那么就会输出f[2]=90,但是很明显这个题最大报销额是95。不过这么写在杭电也能过。我看有人用Q*100作为背包,虽然不会错了,但是因为Q*100太大了,可能会超内存。
#include <iostream> #include <cstring> #include<iomanip> using namespace std; const int MAX_N = 30 + 3; double money[3],dp[MAX_N],value[MAX_N]; double _max; int n; int main() { while(cin >> _max >> n,n) { int cnt = 0; for(int i = 0;i < n;i++) { int m; cin >> m; memset(money,0,sizeof(money)); bool flag = true; char a,b; double v; for(int j = 0;j < m;j++) { cin >> a >> b >> v; if(a == 'A') money[0] += v; else if(a == 'B') money[1] += v; else if(a == 'C') money[2] += v; else flag = false; } if(flag) { if(money[0] + money[1] + money[2] <= min(1000.0,_max) && money[0] <= 600.0 && money[1] <= 600.0 && money[2] <= 600.0) value[cnt++] = money[0] + money[1] + money[2]; } } memset(dp,0,sizeof(dp)); for(int i = 0;i < cnt;i++) { for(int j = cnt;j >= 1;j--) { dp[j] = max(dp[j],dp[j - 1] + value[i]); } } for(int i = cnt;i >= 0;i--) { if(dp[i] <= _max) { cout << fixed << setprecision(2) << dp[i] << endl; break; } } } return 0; }