多重背包问题对比01背包问题,01背包问题是只有选和不选两种情况,多重背包是不止这两种情况,其实是01背包问题的一种扩展,只需要在状态转移时变化一下
代码:
#include<iostream>
#include<algorithm>
#include<cmath>
const int N=110;
int n,m;
int f[N];
using namespace std;
int main(){
cin>>n>>m;
for(int i=0;i<n;i++){
int v,w,s;
cin>>v>>w>>s;
for(int j=m;j>=0;j--){
for(int k=1;k<=s&&k*v<=j;k++){
f[j]=max(f[j],f[j-k*v]+k*w);
}
}
}
cout<<f[m];
}
如果数据范围1000~2000,采用二进制优化方法:把多重背包问题变成01背包问题
考虑给定一个数s,最少把s分成多少个数,分别有选和不选两种方法,可以拼成小于等于s的所有数?
如果s=7,分成1,2,4
0
1=1
2=2
3=1+2
4=4
5=1+4
6=2+4
7=1+2+4
解法分成log2(s)下取整个数,s=7,则拆成2^0=1,2^1=2,2^2=4
代码:
#include<iostream>
#include<algorithm>
#include<cmath>
#include<vector>
const int N=2010;
int n,m;
int f[N];
using namespace std;
struct Good{
int v,w;
};
int main(){
vector<Good> goods;
cin>>n>>m;
for(int i=0;i<n;i++){
int v,w,s;
cin>>v>>w>>s;
for(int k=1;k<=s;k*=2){
s-=k;
goods.push_back({v*k,w*k});
}
if(s>0)goods.push_back({v*s,w*s}) ; //把剩余部分加进去
}
//01背包
for(auto good:goods){
for(int j=m;j>=good.v;j--){
f[j]=max(f[j],f[j-good.v]+good.w);
}
}
cout<<f[m];
}