前置知识
0-1背包:对于每种物品,最多只能选取1次,每种物品存在选与不选
完全背包:对于每种物品,可以无限多次获取
多重背包:对于每种物品,最大获取次数有限,通常可以使用二进制优化并结合0-1背包公式解决问题
一、混合背包的概念
简单来说就是多重背包与完全背包的混合,也就是说既存在可以无限获取的物品,也存在获取上限的物品
二、习题演示
1.洛谷P1833樱花
1.解题思路与代码
通常的思路就是if判断,由于0-1背包可以看成是只有1次的多重背包,所以if两重判断就可以完成对完全背包和多重背包的分离处理
#include<bits/stdc++.h>
typedef long long ll;
using namespace std;
const int N = 1e4+5;
int h1,h2,m1,m2,n;
char d1;
int w[N], v[N], p[N];
int dp[1001];
int main(){
cin >> h1 >> d1 >> m1 >> h2 >> d1 >> m2 >> n;
int d = (h2-h1)*60+m2-m1;
for(int i=1; i<=n; ++i){
cin >> w[i] >> v[i] >> p[i];
}
for(int i=1; i<=n; ++i){
if(p[i] == 0){ //完全背包
for(int j=w[i]; j<=d; ++j){
dp[j] = max(dp[j], dp[j-w[i]]+v[i]);
}
}
else{ //多重背包
//二进制优化
for(auto l=1; l<=p[i]; l<<=1){
for(int j=d; j>=l*w[i]; --j){
dp[j] = max(dp[j], dp[j-l*w[i]] + l*v[i]);
}
p[i] -= l;
}
if(p[i] == 0) continue;
for(int j=d; j>=p[i]*w[i]; --j){
dp[j] = max(dp[j], dp[j-p[i]*w[i]]+p[i]*v[i]);
}
}
}
cout << dp[d];
return 0;
}
总结
1.混合背包没有什么难的点,实际只要会完全背包和多重背包,混合背包也无非就是多加一点判断的事