AC_5. 多重背包问题 II
代码:
//多重背包优化(二进制) /* 1.怎么把多重背包问题转换为01背包问题 v,w拆开重复s份放到数组里面去,每个物品只能用一次 => 二进制拆法 7 7以内选多少个数可以使得7中所有的数都可以组合出来 0-7 1 1 1 1 1 1 1 1 2 4 0 1 2 3 = 1 + 2 4 = 4 5 = 1 + 4 6 = 2 + 4 7 = 1 + 2 + 4 给定一个数s,用多少个数可以表示小于等于s的所有数 答案 log2(s)上取整 s = 10 1 2 4 3 1 2 7 :0-7 3: 0-10 s - 1 - 2 - 4 - 8 分成了log(s)份 1000*log(2000)*2000 = 1000*11*2000 = 2 * 10^7 */ #include<iostream> #include<cstring> #include<algorithm> #include<vector> using namespace std; const int NUM = 2010; int N, V; int dp[NUM]; //定义结构体 v体积,w表示价格 struct Good{ int v, w; }; int main() { vector<Good>goods;//不知道总共的物品有多少个 cin >> N >> V; for (int i = 0; i < N; i++) { int v, w, n; cin >> v >> w >> n; for (int k = 1; k <= n; k *= 2)//拆成2的整次幂 { n -= k; goods.push_back({ v*k, w*k });//放到物品组中去 } if (n>0) goods.push_back({ v*n, w*n });//剩余的 } // 01背包求最大价值 for (auto good:goods) for (int j = V; j >= good.v; j--) { dp[j] = max(dp[j], dp[j - good.v] + good.w); } cout << dp[V] << endl; return 0; }
以大多数人努力程度之低,根本轮不到去拼天赋~