动态规划10-多重背包

题目描述

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

思路分析

区别于完全背包和简单的01背包问题,多重背包问题既不是每个物品只有一件,又不是每个物品有无数件,而是每件物品有相应的限制数量。在这样的限制数量下求背包里的最大价值。但是可以通过将物品数量展开将问题转变成01背包问题。
动态规划10-多重背包_第1张图片
转变成如下:
动态规划10-多重背包_第2张图片
按照动态规划五部曲:

  1. 确定dp[i][j]的含义:当容器体积为j的时候,从下标为1-i的物品中选取物品,使得最终的背包总价值最大
  2. 确定递推关系,对于当前物品i有两种情况,那就是放或者不放。

如果放,那么当前的dp[i][j]=dp[i-1][j-weight[i]]+value[i],也就是当背包容量减少物品i的时候的最大价值加上i的价值
如果不放,那么就延续上一个dp[i-1][j]

  1. 初始化,对于dp[i][0],由于背包容量为0,不管怎么选最终价值都不会超过0,因此将dp[i][0]全部初始化为0;对于dp[0][0],也同样是0。其他的对于dp[0][j],价值就是value[0]。如此一来初始化完毕!
  2. 遍历顺序选择按照物品的顺序进行遍历
  3. 带入验证

代码展示

int main() {
    int bagWeight,n;
    cin >> bagWeight >> n;
    vector<int> weight(n, 0);
    vector<int> value(n, 0);
    vector<int> nums(n, 0);
    for (int i = 0; i < n; i++) cin >> weight[i];
    for (int i = 0; i < n; i++) cin >> value[i];
    for (int i = 0; i < n; i++) cin >> nums[i];

    vector<int> dp(bagWeight + 1, 0);

    for(int i = 0; i < n; i++) { // 遍历物品
        for(int j = bagWeight; j >= weight[i]; j--) { // 遍历背包容量,还是老样子,倒序遍历
            // 以上为01背包,然后加一个遍历个数
            for (int k = 1; k <= nums[i] && (j - k * weight[i]) >= 0; k++) { // 遍历个数
                dp[j] = max(dp[j], dp[j - k * weight[i]] + k * value[i]);
            }
        }
    }

    cout << dp[bagWeight] << endl;
}

你可能感兴趣的:(#,算法设计,动态规划,算法)