今天在准备背包问题的算法模板时,突然想到上学期遗留下的一道混合背包问题,当时刚接触c语言,遇到这种题自然是一筹莫展,写的背包不是超时就是超空间,也有写过二进制的优化,但都以失败告终,如今看来,此题便是不攻自破了,顺便把它写成了万能的背包模板。
题目如下:
该题因为数据量较大,要用到优化来解决超时的问题,我选择了二进制优化,把混合背包转化成0-1背包问题。
二进制优化的原理十分简单,就是通过二进制拼出自然数的方法将一个多重背包拆成几个0-1背包,例如,7可以拆成1,2,4三个数,这三个数能拼出1-7的所有数,由此便把一个多重背包转化成了多个0-1背包,如果数不能刚好被二进制拼出,那就额外加一个余数的背包就行了,例如6可拆成1,2,3,这三个数能拼出1-6的所有数。
由于该题还有无限背包的混合,只要将它转化为总和质量不超过可承载质量的一个多重背包即可。
代码如下:
#include<bits/stdc++.h>
using namespace std;
int dp[10005];
struct node{
int c;
int w;
}bag[1009];
int main() {
int n,m;
while(cin >> n >> m){
memset(dp,0,sizeof dp);
int s=0;
for (int i = 0; i < n; ++i) {
int c1,w1,k1;
cin>>c1>>w1>>k1;
if(k1==0){
k1=m/c1;
}
int tem=1;
while(k1-tem>=0){
bag[s].c=c1*tem;
bag[s++].w=tem*w1;
k1=k1-tem;
tem=tem<<1;
}
if(k1>0){
bag[s].c=c1*k1;
bag[s++].w=k1*w1;
}
}
for(int i=0;i<s;++i){
for(int j=m;j>=bag[i].c;--j){
dp[j]=max(dp[j],dp[j-bag[i].c]+bag[i].w);
}
}
cout<<dp[m]<<endl;
}
return 0;
}
这样就能解各种没有其他约束条件的背包问题了时间复杂度一般来说还较低。