0
点赞
收藏
分享

微信扫一扫

多重背包问题

三分梦_0bc3 2022-03-25 阅读 59
动态规划

在这里插入图片描述

/*多重背包问题*/

#include<iostream>
using namespace std;

int dp[21][1001];
int w[21], v[21], x[21]; //w是物品的重量,v是价值,x是每一种物品有x几个
int n, mw;

int dp1[1001]; //优化空间

int main() {

cin >> n >> mw;
for (int i = 1; i <= n; ++i) {
cin >> v[i] >> w[i] >> x[i]; //价值、重量、个数
}
//正常先遍历物品 再遍历重量 再遍历物品个数
for (int i = 1; i <= n; ++i) {
for (int j = 0; j <= mw; ++j) {
for (int k = 0; k <= x[i] && k * w[i] <= j; ++k) { //判断条件也可以放在for循环
//if(j>=k*w[i]){ //一定要判断条件,让j<k*w[i]的情况不进入循环,否则会超重
dp[i][j] = max(dp[i][j], dp[i - 1][j - k * w[i]] + k * v[i]);
//}
//此处不用和01背包那样有else,因为当k=0时,代表着在j重量情况下不放i物品的情况即dp[i][j]=dp[i-1][j];
}
}
}

cout << dp[n][mw] << endl;

//优化空间
for (int i = 1; i <= n; ++i) {
for (int j = mw; j > 0; --j) {
for (int k = 0; k <= x[i]; ++k) {
if (j >= k * w[i]) {
dp1[j] = max(dp1[j], dp1[j - k * w[i]] + k * v[i]);
}
//此处不用和01背包那样有else,因为当k=0时,代表着在j重量情况下不放i物品的情况即dp[i][j]=dp[i-1][j];
}
}
}
cout << dp1[mw] << endl;
return 0;
}

 重点:二进制优化

 

/*多重背包的二进制优化*/

#include<bits/stdc++.h>
using namespace std;

int dp[1001];
int w[21],v[21],x[21]; //w是物品的重量,v是价值;
int n,mw;
int nw[100],nv[100];

int main() {
cin>>n>>mw;
for(int i=1;i<=n;++i){
cin>>v[i]>>w[i]>>x[i]; //价值、重量、个数
}

int ncnt = 0; //拆成一个一维的背包序列

//每一项进行拆分
for(int i = 1;i<=n;++i){
int k;
//找最大的k,k代表二进制位数
for(k = 1;x[i]-(1<<k)+1>0;++k){
nw[ncnt] = (1<<(k-1))*w[i];
nv[ncnt] = (1<<(k-1))*v[i];
++ncnt;
}
--k;
//最后一项
nw[ncnt] = (x[i]-(1<<k)+1)*w[i];
nv[ncnt] = (x[i]-(1<<k)+1)*v[i];
++ncnt;
}

//转化为0-1背包问题
for(int i = 0;i < ncnt;++i){ //注意这里i从0开始,即2^0
for(int j = mw;j >= nw[i];--j){
dp[j] = max(dp[j],dp[j-nw[i]]+nv[i]);
}
}

cout<<dp[mw];

return 0;
}
/*
5 10
2 1 2
3 5 3
2 5 1
3 4 2
4 3 8
答案:14
*/

 

举报

相关推荐

0 条评论