特征
混合背包,就是把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
acwing混合背包
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;
}