混合背包就是将前面三种的背包问题混合起来,有的只能取一次,有的能取无限次,有的只能取 次。1
例题:luogu1833 樱花
事实上,我们直接对不同的物品按情况讨论即可。
关于混合背包,0/1背包可以看成是多重背包的特例(
),因此,仅考虑两种情况即可。
luogu1833 樱花对应的代码如下:
/* ***********************************************
Author : VFVrPQ
Created Time : 五 2/28 15:39:08 2020
File Name : luogu1833樱花.cpp
Problem :
Description :
Solution :
Tag :
************************************************ */
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <string>
#include <cmath>
#include <cstdlib>
#include <vector>
#include <queue>
#include <stack>
#include <set>
#include <map>
#include <iomanip>
using namespace std;
#define DEBUG(x) cout<<x<<endl;
const int N = 1e4+10;
const int M = 1e9+7;
const int INF = 1e9+7;
string ts, te;
int n;
int t[N],c[N],p[N];
int dp[N];
int getStr(string t){
int i;
int ret = 0;
for (i=0;t[i]!='\0';i++){
if (t[i]==':') break;
ret = ret * 10 + t[i]-'0';
}
ret*=60; //转换成分钟
int now = 0;
for (i+=1;t[i]!='\0';i++){
now = now * 10 + t[i]-'0';
}
return ret+now;
}
int main()
{
cin >> ts >> te >> n;
for (int i=1;i<=n;i++){
cin >> t[i] >> c[i] >> p[i];
}
int maxT = getStr(te) - getStr(ts);
for (int i=1;i<=n;i++){
if (p[i] == 0){//完全背包
for (int j=t[i];j<=maxT;j++) dp[j] = max(dp[j], dp[j-t[i]]+c[i]);
}else {//多重背包
for (int k=1;;k*=2){
int now = k;//当前的物品个数
if (now >= p[i]) now = p[i];//取较小者
for (int j=maxT;j>=now*t[i];j--) dp[j] = max(dp[j], dp[j-now*t[i]]+now*c[i]);//now*的0/1背包
p[i] -= now;
if (p[i]==0) break;
}
}
}
printf("%d\n",dp[maxT]);
//for (int i=0;i<=maxT;i++) printf("%d ",dp[i]);
//printf("%d\n",maxT);
return 0;
}