题目链接
http://acm.hdu.edu.cn/showproblem.php?pid=2191
思路
由于每种大米可能不止一袋,所以是多重背包问题,可以直接使用解决多重背包问题的方法,也可以将多重背包转化为01背包后求解。
代码
01背包:
1 #include <algorithm> 2 #include <iostream> 3 #include <cstring> 4 #include <cstdio> 5 using namespace std; 6 7 const int N = 100 * 20 + 10; 8 int m[N], w[N]; //记录每袋大米的价格、重量 9 int dp[N]; 10 11 int main() 12 { 13 //freopen("hdoj2191.txt", "r", stdin); 14 int t; 15 cin >> t; 16 while (t--) 17 { 18 int n, k; 19 cin >> n >> k; 20 int cnt = 0; //共有cnt袋大米 21 for (int i = 0; i < k; i++) 22 { 23 int p, h, c; 24 cin >> p >> h >> c; 25 for (int j = 0; j < c; j++) 26 { 27 m[cnt] = p; 28 w[cnt] = h; 29 cnt++; 30 } 31 } 32 33 memset(dp, 0, sizeof(dp)); 34 for (int i = 0; i < cnt; i++) 35 { 36 for (int j = n; j >= m[i]; j--) 37 dp[j] = max(dp[j], dp[j - m[i]] + w[i]); 38 } 39 cout << dp[n] << endl; 40 } 41 return 0; 42 }
多重背包:
#include <algorithm> #include <iostream> #include <cstring> #include <cstdio> using namespace std; const int N = 20 * 100 + 10; int m[N], w[N], num[N]; int dp[N]; void zero_one_pack(int weight, int value, int capacity) { for (int i = capacity; i >= weight; i--) //逆序 dp[i] = max(dp[i], dp[i - weight] + value); } void complete_pack(int weight, int value, int capacity) { for (int i = weight; i <= capacity; i++) //正序 dp[i] = max(dp[i], dp[i - weight] + value); } void multiple_pack(int weight, int value, int amount, int capacity) { if (weight*amount >= capacity) complete_pack(weight, value, capacity); else { int k = 1; while (k <= amount) { zero_one_pack(weight*k, value*k, capacity); amount -= k; k *= 2; } zero_one_pack(weight*amount, value*amount, capacity); } } int main() { //freopen("hdoj2191.txt", "r", stdin); int t; cin >> t; while (t--) { int n, k; cin >> n >> k; for (int i = 0; i < k; i++) cin >> m[i] >> w[i] >> num[i]; memset(dp, 0, sizeof(dp)); for (int i = 0; i < n; i++) multiple_pack(m[i], w[i], num[i], n); cout << dp[n] << endl; } return 0; }