最大報銷額 (HDU - 1864,01揹包)
阿新 • • 發佈:2018-11-23
首先強調不超過600元的是一張發票上同一類商品的額度總和,而題意描述的是單項物品,坑!
輸入有空格字元,需要注意一下。然後每一張發票輸入完之後,判斷是否滿足報銷條件,如果滿足則存入w陣列。
之後就是一個01揹包問題了,只不過這裡的價值和花費相等,只需要一個數組存下即可。不過利用dp陣列進行狀態轉移的時候需要注意,因為最後的精度要求是小數點後兩位,所以要遍歷到每一種狀態的話,要將整體的資料都擴大一百倍,否則當前狀態沒法用陣列下標表示。最後將結果再縮小100倍即可。
程式碼如下(未精簡,略冗長):
#include <iostream> #include <string> #include <cstring> #include <cmath> #include <algorithm> #include <cstdio> using namespace std; #define mem(a, i) memset(a, i, sizeof(a)) #define INF 0x3f3f3f3f int dp[4999000]; int main() { //freopen("in.txt", "r", stdin); int n; double q; while(cin >> q >> n && n) { int w[1010]; int m; char s, c; mem(w, 0); for(int i = 1; i <= n; ++ i) { cin >> m; bool flag = true; double h, A = 0, B = 0, C = 0, sum = 0; for(int j = 0; j < m; ++ j) { c = getchar(); s = getchar(); c = getchar(); if(!(s == 'A' || s == 'B' || s == 'C')) { flag = false; } cin >> h; if(s == 'A') { A += h; } else if(s == 'B') { B += h; } else if(s == 'C') { C += h; } } if(A > 600 || B > 600 || C > 600) { flag = false; } else { sum += (A + B + C); } if(flag && sum <= 1000) { w[i] = (sum * 100); } else { w[i] = INF; } } mem(dp, 0); int p = (q * 100); for(int i = 1; i <= n; ++ i) { for(int j = q * 100; j >= 0; --j) { if(j < w[i]) { dp[j] = dp[j]; } else { dp[j] = max(dp[j - w[i]] + w[i], dp[j]); } } } printf("%.2lf\n", dp[p] * 1.0 / 100); } return 0; }