0-1背包二维变一维(滚动数组解法)

206 阅读2分钟

0-1背包问题滚动数组解法

有n件物品和一个最多能装重量为w的背包,第i件物品的重量是weight[i],得到的价值为value[i]。每件物品只能使用一次,求解将哪些物品装入背包中物品的价值总和最大。

动态规划-滚动数组的方式解决

使用动态规划解决0-1背包问题时,定义的dp数组可以是一个二维数组,即dp[i][j]表示在0-i件物品中挑选,背包容量为j可获取的最大价值。
实际上,dp数组也可以定义为一维数组。
dp[j]表示背包容量为j的背包可装的最大价值。
dp数组转换为一维数组后,有几个需要注意的问题:

  • 实际上,在遍历物品中,每一层的循环都会重新初始化dp数组,因此下一层的背包容量的循环,使用的dp数组是上一层进行过初始化的数组。
  • 只能先遍历物品再遍历背包容量
  • 遍历背包容量时需要倒序,因此如果正序遍历背包容量的话,会出现重复装入一个物品的情况。

286f4c3608939cc5ce69e1b0187b237.jpg

动态规划步骤:

  • (1)dp[j]表示背包容量为j可装的最大价值
  • (2)递推公式:dp[j] = Math(dp[j],dp[j - weighjt[i]] + value[i]),dp[j]在上一层循环中重新初始化
  • (3)dp数组初始化:每一层循环dp数组都会重新初始化,所以dp数组不用再进行初始化
  • (4)遍历顺序:先正序遍历物品,再倒序遍历背包容量即可
  • (5)模拟dp数组
代码实现
  public static void main(String[] args) {
        int[] weight = {1, 3, 4};
        int[] value = {15, 20, 30};
        int bagWight = 4;
        testWeightBagProblem(weight, value, bagWight);
    }

    public static void testWeightBagProblem(int[] weight, int[] value, int bagWeight){
        int wLen = weight.length;
        //定义dp数组:dp[j]表示背包容量为j时,能获得的最大价值
        int[] dp = new int[bagWeight + 1];
        //遍历顺序:先遍历物品,再遍历背包容量
        for (int i = 0; i < wLen; i++){
            for (int j = bagWeight; j >= weight[i]; j--){
                dp[j] = Math.max(dp[j], dp[j - weight[i]] + value[i]);
            }
        }
        //打印dp数组
        for (int j = 0; j <= bagWeight; j++){
            System.out.print(dp[j] + " ");
        }
    }