#include<iostream>
using namespace std;constint N =110;int n,m;int v[N],w[N],s[N];int f[N][N];intmain(){
cin >> n >> m;for(int i=1;i<=n;i++) cin >> v[i]>> w[i]>> s[i];for(int i=1;i<=n;i++)for(int j=0;j<=m;j++)for(int k=0;k <=s[i]&& k * v[i]<=j;k++)// 限制1:数量,限制2:体积
f[i][j]=max(f[i][j],f[i-1][j-v[i]* k]+ w[i]* k);
cout<<f[n][m]<<endl;return0;}
边读入边更新
#include<iostream>
using namespace std;constint N =110;int n,m;int f[N][N];intmain(){
cin >> n >> m;for(int i=1;i<=n;i++){
int v,w,s;
cin >> v >> w >> s;for(int j=0;j<=m;j++)for(int k =0;k<=s && k * v <= j;k++)
f[i][j]=max(f[i][j],f[i-1][j - k * v]+ k * w);}
cout<<f[n][m]<<endl;return0;}
利用滚动数组优化掉一维
#include<iostream>
using namespace std;constint N =110;int n,m;int v[N],w[N],s[N];int f[N];intmain(){
cin >> n >> m;for(int i=1;i<=n;i++) cin >> v[i]>> w[i]>> s[i];for(int i=1;i<=n;i++)for(int j=m;j>=0;j--)for(int k=0;k<=s[i]&& k * v[i]<=j;k++)
f[j]=max(f[j],f[j - k * v[i]]+ k * w[i]);
cout<<f[m]<<endl;return0;}
多重背包问题 II(二进制优化,由此看出多重背包也是特殊的01背包)
题目描述(注意数据范围已扩大到1000)
代码(时间复杂度:O(NVlog(S))
#include<iostream>
using namespace std;constint N =12010, M =2010;// N = 2000 * log(2000)// 核心:利用二进制把s份拆成 log(s) 份int n,m;int v[N], w[N];int f[M];intmain(){
cin >> n >> m;int cnt =0;for(int i=1;i<=n;i++){
int a,b,s;
cin >> a >> b >> s;int k =1;while(k <= s){
cnt ++;
v[cnt]= a * k;
w[cnt]= b * k;
s -= k;
k *=2;}if(s >0)// 剩下的凑成一组{
cnt ++;
v[cnt]= a * s;
w[cnt]= b * s;}}
n = cnt;// 总共有cnt组,做一遍01背包for(int i=1;i<=n;i++)for(int j = m; j >= v[i]; j --)
f[j]=max(f[j],f[j - v[i]]+ w[i]);
cout<<f[m]<<endl;return0;}
简洁版(边读入边更新,和滚动数组优化)
#include<iostream>
using namespace std;constint N =12010, M =2010;// N = 2000 * log(2000)// 核心:利用二进制把s份拆成 log(s) 份int n,m;int f[M];intmain(){
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){
for(int j = m;j >= k * v; j --)
f[j]=max(f[j], f[j - k * v]+ k * w);
s -= k;}if(s){
for(int j = m;j >= s * v;j --)
f[j]=max(f[j],f[j-s * v]+ s * w);}}
cout<<f[m]<<endl;return0;}
多重背包问题 III
题目描述(注意数据范围)
单调队列优化(时间复杂度:O(NV))
代码
#include<iostream>#include<cstring>
using namespace std;constint N =20010;int n,m;int f[N],g[N],q[N];intmain(){
cin >> n >> m;for(int i=0;i<n;i++){
int v,w,s;
cin >> v >> w >> s;memcpy(g,f,sizeof f);for(int j =0;j<v;j++)// 这里的j是在枚举 j % v的余数,范围从0~v-1{
int hh=0,tt=-1;for(int k =j;k<=m;k+=v){
if(hh <= tt && q[hh]< k - s * v) hh ++;if(hh <= tt) f[k]=max(f[k],g[q[hh]]+(k - q[hh])/ v * w);while(hh <= tt && g[q[tt]]-(q[tt]- j)/ v * w <= g[k]-(k - j)/ v * w) tt--;
q[++ tt]= k;}}}
cout<<f[m]<<endl;return0;}