多重背包-二进制优化
核心思想
1. 回到定义f[i,j]表示从前i个物品中选,体积总和超过j的方案的集合,属性是集合中的最大值
2. 将每个物品拆成若干个新物品,再对这些物品进行01背包选择时,我们只需要考虑拆分后的这些物品能不能组合成原来的物品即可,而不需要管他们是如何组合的,因为定义是说从这些物品中选,只要能组合成所有点方案即可。通过证明发现二进制优化可以组合成所有点方案。
#include <iostream>
#include <cstring>
#include <algorithm>
using namespace std;
const int N = 12010;
int n, m;
int v[N], w[N];
int f[N];
int main() {
cin >> n >> m;
int cnt = 0;
for (int i = 1; i <= n; i++) {
int a, b, s;
cin >> a >> b >> s;
int k = 1;
while (k < s) {
v[++cnt] = k * b;
w[cnt] = k * a;
s -= k;
k *= 2;
}
if (s > 0) {
v[++cnt] = s * b;
w[cnt] = s * a;
}
}
n = cnt;
for (int i = 1; i <= n; i++) {
for (int j = m; j >= w[i]; j--) {
f[j] = max(f[j], f[j - w[i]] + v[i]);
}
}
cout << f[m] << endl;
return 0;
}