Water2Wine

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

背包问题可以基本上分为01背包,多重背包,完全背包,本质上都可以化为01背包来解决

01背包的递推式:dp[i][j] = Math.max(dp[i - 1][j - weight] + value[i], dp[i - 1][j])

完全背包的递推式:dp[i][j] = Math.max(dp[i][j - weight] + value, dp[i - 1][j])

多重背包的递推式:dp[i][j] = ∑(0-k)Math.max(dp[i - 1][j - k * weight] + k * value[i], dp[i - 1][j])

根据递推式的不同,01背包在空间压缩的代码中逆序生成dp,完全背包顺序生成dp,多重背包可以将k化为多个2的幂及和的差值转换为01背包,如果k足够大,也可以转换为完全背包

    // 01背包
    // dp[i][j] = Math.max(dp[i - 1][j - weight] + value, dp[i - 1][j])
    private static void getValueOfZeroBag(int i, int k) {
        for (int j = W;j >= 1;j--) {
            if (k * weight[i] <= j) {
                sum[j] = Math.max(sum[j], sum[j - k * weight[i]] + k * value[i]);
            }
        }
    }
    // 完全背包
    // dp[i][j] = Math.max(dp[i][j - weight] + value, dp[i - 1][j])
    private static void getValueOfFullBag(int i) {
        for (int j = 1;j <= W;j++) {
            if (weight[i] <= j) {
                sum[j] = Math.max(sum[j], sum[j - weight[i]] + value[i]);
            }
        }
    }
    // 多重背包
    // 递推式可以分别转换为完全背包和01背包
    private static void getValueOfMultiBag(int i) {
        if (weight[i] * count[i] >= W) {
            // 转换为完全背包
            getValueOfFullBag(i);
        } else {
            // 将count[i]分成多个2的幂次方及一个差值
            int m = 1;
            for (;m <= count[i];m *= 2) {
                getValueOfZeroBag(i, m);
            }
            getValueOfZeroBag(i, count[i] - m / 2);
        }
    }
posted on 2020-08-19 14:51  Water2Wine  阅读(89)  评论(0编辑  收藏  举报