AcWing 05多重揹包問題II
阿新 • • 發佈:2021-08-13
題目連結 AcWing 5.多重揹包問題II
二進位制優化多重揹包
二進位制優化原理(不難證明)
對於一個整數S,不妨設 S = \((1101011)_{2}\) 為 7位2進位制整數,
我們可以由{\({2^0,2^1,2^2,2^3,2^4,2^5,2^6,2^7}\)}(集合中的元素要麼選,要麼不選)
組合成[0, S]內的任意一個整數
Case 1
#include <iostream> #include <cstring> #include <algorithm> using namespace std; const int N = 12000; int v[N], w[N]; int f[N]; int n, m, cnt; int main() { cin >> n >> m; for (int i = 0; i < n; i ++ ) { int a, b, s; cin >> a >> b >> s; int k = 1; while(k < s) { cnt ++; v[cnt] = a * k; w[cnt] = b * k; s -= k; k *= 2; } if(s > 0) { cnt ++; v[cnt] = a * s; w[cnt] = b * s; } } n = cnt; for(int i = 1; i <= n; i ++) for(int j = m; j >= v[i]; j --) f[j] = max(f[j], f[j - v[i]] + w[i]); cout << f[m] << endl; return 0; }
Case 2
#include <iostream> #include <algorithm> #include <vector> using namespace std; const int N = 2010; int n, m; int f[N]; struct GOOD { int v, w; }; int main() { cin >> n >> m; vector<GOOD> goods; for(int i = 0; i < n; i ++) { int a, b, s; cin >> a >> b >> s; int k = 1; while(k < s) { goods.push_back({k * a, k * b}); s -= k, k *= 2; } if(s > 0) goods.push_back({s * a, s * b}); } for(auto good : goods) for(int j = m; j >= good.v; j --) f[j] = max(f[j], f[j - good.v] + good.w); cout << f[m] << endl; return 0; }