今天也是刚做了一下混合背包,原理很简单,就是把多重背包进行二进制优化转化为01背包,而01背包和完全背包不用变,最后判断是01背包还是完全背包进行遍历即可。
原题链接:7. 混合背包问题 - AcWing题库
ac代码:
#include <bits/stdc++.h>
using namespace std;
const int N = 1e4 + 5;
const int M = 1e6 + 5;
int n, m, cnt;
int dp[N];
int v[N], w[N], s[N];
int a[M], b[M], c[M];
int main()
{
cin >> n >> m;
for (int i = 1; i <= n; i++) {
cin >> v[i] >> w[i] >> s[i];
}
for (int i = 1; i <= n; i++) {
if (s[i] < 0) {//本身就是01背包,直接存起来
cnt++;
a[cnt] = v[i];
b[cnt] = w[i];
c[cnt] = 1;
}
else if (s[i] == 0) {//原来是完全背包,也是直接存起来
cnt++;
a[cnt] = v[i];
b[cnt] = w[i];
c[cnt] = 0;
}
else {//原来是多重背包,二进制优化,变成01背包后再存起来
for (int j = 1; j <= s[i]; j *= 2) {
s[i] -= j;
cnt++;
a[cnt] = v[i] * j;
b[cnt] = w[i] * j;
c[cnt] = 1;
}
if (s[i] > 0) {
cnt++;
a[cnt] = v[i] * s[i];
b[cnt] = w[i] * s[i];
c[cnt] = 1;
}
}
}
for (int i = 1; i <= cnt; i++) {
if (c[i] == 1) {//01背包
for (int j = m; j >= a[i]; j--) {
dp[j] = max(dp[j], dp[j - a[i]] + b[i]);
}
}
else if (c[i] == 0) {//安全背包
for (int j = a[i]; j <= m; j++) {
dp[j] = max(dp[j], dp[j - a[i]] + b[i]);
}
}
}
cout << dp[m] << endl;
return 0;
}