• 完全背包


    完全背包

    n件物品和一个最多能背重量为w 的背包。第i件物品的重量是weight[i],得到的价值是value[i]每件物品有无限个(也就是可以每个物品可以多次放入背包),求解将哪些物品装入背包里物品价值总和最大。

    示例1:

    输入:n = 3, w = 4, weight = [1, 3, 4], value = [15, 20, 30]
    输出:60

    解题思路

    经典动态规划问题。完全背包和01背包的不同之处在于完全背包中的每种物品有无限多个

    二维数组解法

    针对示例1,如果是01背包问题,可以得到的dp数组如下图所示:

    从上图可以看出,dp[1][3]是由dp[0][3]dp[0][0]推导出来的,也就是说dp[i][j]是由dp[i - 1][j]dp[i - 1][j - weight[i]]+ value[i]推导出来的。从而可以得出结论在01背包中,当前状态只与上方和左上方的状态有关系。

    如果是完全背包问题,可以得到的dp数组如下图所示:

    从上图可以看出,dp[1][3]是由dp[0][3]dp[1][0]推导出来的,也就是说dp[i][j]是由dp[i - 1][j]dp[i][j - weight[i]] + value[i]推导出来的。从而可以得出结论在完全背包中,当前状态只与上方和左方的状态有关系。

    于是,有

    01背包的递推公式:

    dp[i][j] = max(dp[i - 1][j], dp[i - 1][j - weight[i]]+ value[i])

    完全背包的递推公式:

    dp[i][j] = max(dp[i - 1][j], dp[i][j - weight[i]]+ value[i])

    对于完全背包dp数组的初始化,从上图来看还是有些复杂的。这可以通过给dp数组添加一行来解决初始化的麻烦,也就是从从没有物品时考虑。这样物品0的下标就从1开始了。

    C++

    class Solution {
    public:
        int completeBackpake(vector<int> weight, vector<int> value, int bagsize) {
            vector<vector<int>> dp(weight.size() + 1, vector<int>(bagsize + 1, 0));
            for (int i = 1; i < weight.size() + 1; i++) {
                for (int j = weight[i - 1]; j < bagsize + 1; j++) {
                    dp[i][j] = max(dp[i - 1][j], dp[i][j - weight[i - 1]] + value[i - 1]);
                }
            }
            return dp[weight.size()][bagsize];
        }
    };

    JavaScript

    /**
     * @param {number[]} weight
     * @param {number[]} value
     * @param {number} bagsize
     */
    // 二维数组
    function completeBackpack(weight, value, bagsize) {
        const dp = Array(weight.length + 1).fill(0).map(item => Array(bagsize + 1).fill(0));
        for (let i = 1; i < weight.length + 1; i++) {
            for (let j = weight[i - 1]; j < bagsize + 1; j++) {
                dp[i][j] = Math.max(dp[i - 1][j], dp[i][j - weight[i - 1]] + value[i - 1]);
            }
        }
        return dp[weight.length][bagsize];
    }

    一维数组解法

    0-1背包问题 和 完全背包问题 的一维数组解法主要是 遍历顺序不一样。

    • 用滚动数组的方式优化0-1背包问题时,先正序遍历物品,再倒序遍历背包(必须先物品后背包)。 因为当前状态只与上方和左上方的状态有关系。递推公式为dp[j] = max(dp[j], dp[j - weight[i]]+ value[i])

    • 而用滚动数组的方式优化完全背包问题时,先正序遍历物品,再正序遍历背包(也可以先正序遍历背包,再正序遍历物品)。因为当前状态只与上方和左方的状态有关系。递推公式为dp[j] = max(dp[j], dp[j - weight[i]]+ value[i])

    C++

    class Solution {
    public:
        int completeBackpake(vector<int> weight, vector<int> value, int bagsize) {
            vector<int> dp(bagsize + 1, 0);
            for (int i = 0; i < weight.size(); i++) {
                for (int j = weight[i]; j < bagsize + 1; j++) {
                    dp[j] = max(dp[j], dp[j - weight[i]] + value[i]);
                }
            }
            return dp[bagsize];
        }
    };

    JavaScript

    /**
     * @param {number[]} weight
     * @param {number[]} value
     * @param {number} bagsize
     */
    // 一维数组
    function completeBackpack(weight, value, bagsize) {
        const dp = Array(bagsize + 1).fill(0);
        for (let i = 0; i < weight.length; i++) {
            for (let j = weight[i]; j < bagsize + 1; j++) {
                dp[j] = Math.max(dp[j], dp[j - weight[i]] + value[i]);
            }
        }
        return dp[bagsize];
    }

     

     

  • 相关阅读:
    [react002] component基本用法
    [react001] 使用webpack自动构建react 项目
    [Elixir009]像GenServer一样用behaviour来规范接口
    [Elixir008]Nested Module里的动态函数调用方式
    [Elixir007] on_definition规范函数定义时的各种潜规则
    [Elixir006]CSV(Comma-separated values)处理
    [Elixir005] 查看指定数据的详细信息 i helper
    [Elixir004]通过环境变量(Environment Variables)来管理config
    [Elixir003] Mix Archives
    [Elixir002]节点启动后自动连接其它节点
  • 原文地址:https://www.cnblogs.com/wltree/p/15969127.html
Copyright © 2020-2023  润新知