多重背包问题

多重背包

多重背包与零一背包不同的是,零一背包中的物品是不可以重复拿取的,只可以拿取当前物品或者不拿取当前物品,不可以拿取多个,完全背包的物品是可以任意拿取多个的来构成不超过背包容量并且构成的总价值是最大的.

题目

有N种物品和一个容量为V的背包。第i种物品最多有n[i]件可用,每件费用是c[i],价值是w[i]。求解将哪些物品装入背包可使这些物品的费用总和不超过背包容量,且价值总和最大。

基本算法(直接算)

f[i][v]=max{f[i-1][v-kc[i]]+kw[i]|0<=k<=n[i]}
复杂度是O(V*Σn[i])

代码实现

 
 
#include <iostream>
#include <algorithm>
#define N 1002
using namespace std;
 
int f[N];
int w[N];
int v[N];
int s[N];
 
int main() {
    int n,W; cin >> n >> W;
    for(int i=1;i<=n;i++) {
        cin >> w[i] >> v[i] >> s[i];
    }
    for(int i=1;i<=n;i++) {
        for(int j=W;j>=w[i];j--) {
            for(int k=0;k<=s[i] && k*w[i] <=j ;k++) {
                f[j] = max(f[j],f[j-k*w[i]] + k*v[i]);
            }
        }
    }
    cout << f[W] <<endl;
    return 0;
}

转换为01背包分析

多重背包问题是0-1背包问题的一个扩展,它可以通过转变变长0-1背包问题来求解。因为每个物品都有Ni,可以把Ni个物品分开,看成是不同的物品,不过是有相同体积和价值的不同物品。看成是有N=Σ(k,1)Ni个物品的0-1背包问题

伪代码

for i 遍历物品
    for j 遍历体积 从小到大
        for k 遍历当前物品个数
            当k*体积<=背包容量的时候 说明我们的背包是可以放下这么多物品的
            dp[i][j]=max ( dp[i-1][j-k*wi]+k*vi  ,   dp[i-1[j])
            这个表达式的意思就是 要么选择K个这样的物品,要么不选,看看哪个是最优的解,然后更新即可

            当k*体积<背包容量的时候说明我们的背包是放不下这么多物品的
            直接就是dp[i][j]=dp[i-1][j]
posted @ 2021-03-24 10:39  唐坣  阅读(91)  评论(0)    收藏  举报