0
点赞
收藏
分享

微信扫一扫

多重背包问题

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

在这里插入图片描述

/*多重背包问题*/

#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 条评论