lotus

贵有恒何必三更眠五更起 最无益只怕一日曝十日寒

  博客园  :: 首页  :: 新随笔  :: 联系 :: 订阅 订阅  :: 管理

 

目录 

  • 01背包 二维写法
  • 01背包 一维写法
  • 完全背包 二维 带枚举写法
  • 完全背包 二维 普通写法
  • 完全背包 一维写法
  • 多重背包 二维写法
  • 多重背包 一维写法
  • 多重背包 一维写法二进制优化

 

1.  01背包 二维写法

  • dp[i][j] = Math.max(dp[i - 1][j], dp[i - 1][j - w[i - 1]] + v[i - 1])
        // 填写动态规划表
        for (int i = 1; i <= n; i++) {
            for (int j = 1; j <= C; j++) {
                if (j < w[i - 1]) {
                    // 第i种物品的重量大于当前背包的剩余容量,不能放入
                    dp[i][j] = dp[i - 1][j];
                } else {
                    // 第i种物品的重量小于等于当前背包的剩余容量,可以选择放入或不放入
                    dp[i][j] = Math.max(dp[i - 1][j], dp[i - 1][j - w[i - 1]] + v[i - 1]);
                }
            }
        }

 

 

2.   01背包 一维写法

 

  • dp[j] = Math.max(dp[j], dp[j - w[i - 1]] + v[i - 1])  注:j逆序
        for (int i = 1; i <= N; i++) {
            for (int j = C; j >= 0; j--) {
                if (j >= w[i - 1]) {
                    dp[j] = Math.max(dp[j], dp[j - w[i - 1]] + v[i - 1]);
                }
            }
        }

  

3.   完全背包 二维 带枚举写法

  • dp[i][j] = Math.max(dp[i][j], dp[i - 1][j - k * v[i - 1]] + k * w[i - 1])
        // 状态转移
        for (int i = 1; i <= n; i++) {
            for (int j = 1; j <= V; j++) {
                dp[i][j] = dp[i - 1][j]; // 不装第i种物品
                for (int k = 0; k * v[i - 1] <= j; k++) { // 枚举装k个第i种物品
                    dp[i][j] = Math.max(dp[i][j], dp[i - 1][j - k * v[i - 1]] + k * w[i - 1]); // 比较不装和装第i种物品的最大价值
                }
            }
        }

  

4.  完全背包 二维 普通写法

  • dp[i][j] = Math.max(dp[i - 1][j], dp[i][j - v[i - 1]] + w[i - 1])
        for (int i = 1; i <= N; i++) {
            for (int j = v[i - 1]; j <= C; j++) {
                dp[i][j] = Math.max(dp[i - 1][j], dp[i][j - v[i - 1]] + w[i - 1]);
            }
        }

  



 

5.  完全背包 一维写法

  • dp[j] = Math.max(dp[j], dp[j - v[i - 1]] + w[i - 1])  注:j 顺序
        for (int i = 1; i <= N; i++) {
            for (int j = v[i - 1]; j <= C; j++) {
                dp[j] = Math.max(dp[j], dp[j - v[i - 1]] + w[i - 1]);
            }
        }

 

注意
这里的 dp[j] = Math.max(dp[j], dp[j - v[i - 1]] + w[i - 1])
实际是 dp[i][j] = Math.max(dp[i - 1][j], dp[i][j - v[i - 1]] + w[i - 1]) 的简化,
这里用到了 dp[i][j - v[i - 1]],也就是说 计算当前层 不止用到了上一层,还用到了本层比较小的容量,这就是为什么必须正序的原因

6.   多重背包 二维写法

  • dp[i][j] = Math.max(dp[i][j], dp[i - 1][j - k * v[i]] + k * w[i])
        for (int i = 1; i <= N; i++) { // 遍历物品
            for (int j = 0; j <= V; j++) { // 遍历背包容量
                for (int k = 0; k <= s[i] && k * v[i] <= j; k++) { // 遍历物品数量
                    dp[i][j] = Math.max(dp[i][j], dp[i - 1][j - k * v[i]] + k * w[i]); // 状态转移
                }
            }
        }

  

7.  多重背包 一维写法

  • dp[j] = Math.max(dp[j], dp[j - k * v[i - 1]] + k * w[i - 1])
        for (int i = 1; i <= N; i++) {
            for (int j = C; j >= v[i - 1]; j--) {
                for (int k = 0; k <= s[i - 1] && k * v[i - 1] <= j; k++) {
                    dp[j] = Math.max(dp[j], dp[j - k * v[i - 1]] + k * w[i - 1]);
                }
            }
        }

  

 

8. 多重背包 一维写法二进制优化

  •  dp[j] = Math.max(dp[j], dp[j - k * v[i]] + k * w[i])
        for (int i = 1; i <= N; i++) { // 遍历物品
            int k = 1; // 拆分因子
            while (k <= s[i]) { // 拆分数量不超过原数量
                for (int j = V; j >= k * v[i]; j--) { // 遍历背包容量
                    dp[j] = Math.max(dp[j], dp[j - k * v[i]] + k * w[i]); // 状态转移
                }
                s[i] -= k; // 减去已拆分的数量
                k <<= 1; // 拆分因子翻倍
            }
            if (s[i] > 0) { // 如果还有剩余数量
                for (int j = V; j >= s[i] * v[i]; j--) { // 遍历背包容量
                    dp[j] = Math.max(dp[j], dp[j - s[i] * v[i]] + s[i] * w[i]); // 状态转移
                }
            }
        }

 

 

posted on 2023-07-08 17:15  白露~  阅读(10)  评论(0编辑  收藏  举报