特征
混合背包,就是把01,完全,多重背包混合起来
物品一共有三类:
第一类物品只能用1次(01背包);
第二类物品可以用无限次(完全背包);
第三类物品最多只能用 si
次(多重背包);
板子
for (int i = 1;i <= n;i++) {
cin >> c[i] >> w[i] >> s;
if (s == 0) {//完全背包
for (int j = c[i];j <= v;j++) {
dp[j] = max(dp[j], dp[j - c[i]] + w[i]);
}
}
else if (s == 1) {//01背包
for (int j = v;j >= c[i];j--) {
dp[j] = max(dp[j], dp[j - c[i]] + w[i]);
}
}
else {//多重背包
int num = min(s, v / c[i]);
for (int k = 1;num > 0;k <<= 1) {
if (k > num)k = num;
num -= k;
for (int j = v;j >= c[i] * k;j--) {
dp[j] = max(dp[j], dp[j - c[i] * k] + w[i] * k);
}
}
}
}
板子题1
ACcode
#include<bits/stdc++.h>
using namespace std;
const int M = 1e5 + 9;
int c[M], w[M], dp[M];
int main()
{
ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);
int n, v;cin >> n >> v;
int s = 0;
for (int i = 1;i <= n;i++) {
cin >> c[i] >> w[i] >> s;
if (s == -1) {
for (int j = v;j >= c[i];j--) {
dp[j] = max(dp[j], dp[j - c[i]] + w[i]);
}
}
else if (s == 0) {
for (int j = c[i];j <= v;j++) {
dp[j] = max(dp[j], dp[j - c[i]] + w[i]);
}
}
else {
int num = min(s, v / c[i]);
for (int k = 1;num > 0;k <<= 1) {
if (k > num)k = num;
num -= k;
for (int j = v;j >= c[i] * k;j--) {
dp[j] = max(dp[j], dp[j - c[i] * k] + w[i] * k);
}
}
}
}
cout << dp[v];
return 0;
}