200.00 3 2 A:23.50 B:100.00 1 C:650.00 3 A:59.99 A:120.00 X:10.00 1200.00 2 2 B:600.00 A:400.00 1 C:200.50 1200.50 3 2 B:600.00 A:400.00 1 C:200.50 1 A:100.00 100.00 0
123.50 1000.00 1200.50
注意题目中有几个读题的陷阱:
①一旦有其他的物品,该发票就不能报销。
②单样物品,不管多少件,和如果超过600就不能报销
做题的时候要把钱数扩大100倍,这样方便转化为背包问题。
代码如下:
#include <cstdio> #include <cstring> #include <algorithm> using namespace std; int c[33]; int dp[3000011]; int main() { int v,m; double t; bool flag; int num; while (~scanf ("%lf %d",&t,&m)) { if (m == 0) break; memset (dp,0,sizeof (dp)); v = (int)(t * 100); //把钱数扩大100倍 num = 1; for (int i = 1 ; i <= m ; i++) { int l; scanf ("%d",&l); char k; double p; double A,B,C; A = B = C = 0; for (int j = 1 ; j <= l ; j++) { flag = true; scanf (" %c:%lf",&k,&p); if (k == 'A' && p <= 600) A += p; else if (k == 'B' && p <= 600) B += p; else if (k == 'C' && p <= 600) C += p; else flag = false; } if (flag && A <= 600 && B <= 600 && C <= 600 && (A + B + C) <= 1000) //注意读题 c[num++] = (A + B + C) * 100; } for (int i = 1 ; i < num ; i++) { for (int j = v ; j >= c[i] ; j--) { dp[j] = max (dp[j] , dp[j - c[i]] + c[i]); } } t = (double)dp[v] / 100.0; printf ("%.2lf\n",t); } return 0; }