My Sixth-eighth Page - 0-1背包理论基础(滚动数组) - By Nicolas

小尼写的这篇page是先对0-1背包上一篇的二维数组求解做一个优化,小尼在这里优化成一维数组进行对应的求解。我们发现可以把dp[i-1]那一层拷贝到dp[i]上,表达式完全可以是:dp[i][j] = max(dp[i][j], dp[i][j - weight[i]] + value[i]);我们看到这一个思路,我们其实可以想到我们为什么不直接用一个一维数组来表示:dp[j]即可,这个数组小尼在这里也是称为滚动数组,滚动的由来就是我们满足上一层的条件,我们可以进行重复的利用,并且直接拷贝到当前层。

小尼继续来给各位分析一下动规五部曲:

第一步:确定dp数组的定义

在一维dp数组中,dp[j]表示:容量为j的背包,所背的物品价值可以最大为dp[j]

第二步:一维dp数组的递推公式

其实我们递推公式的推导也是从两个方向进行对应的推到,我们也只有两种进行的方式,要么就是放入i,要么就是不放入。一个是取自己dp[i]相当于二位dp数组中的dp[i-1][j],即是不放入物品i;一个是取dp[j-weight[i]] + value[i],即放入物品i,指定是最大的,毕竟是求最大的价值,所以我们的递归公式就是:dp[j] = max(dp[j],dp[j - weight[i]] + value[i]);

第三步:一维数组如何进行初始化

其实因为我们这里直接就是一维数组,所以我们的初始化也是比较简单的,直接就是dp[0] = 0,因为背包容量为0所背的物品的最大的价值就是0.

第四步:一维dp数组遍历顺序

for(int i = 0; i < weight.size(); i++) { // 遍历物品
    for(int j = bagWeight; j >= weight[i]; j--) { // 遍历背包容量
        dp[j] = max(dp[j], dp[j - weight[i]] + value[i]);

    }
}

这边就不像二维遍历一样了,这里遍历的顺序是需要先遍历物品,然后再遍历背包的容量,我们再这里跟二维遍历就不一样,小尼也在这里跟大家说明一下原因,我们这里的第二层for循环的遍历是从bagWeight开始的,原因是我们需要保证每一件物品一定只能取出一次,一旦我们从头开始进行对应的遍历,我们的物品就会取多次,所以我们采取从后遍历的顺序进行

第五步:最后只需要导出我们的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] + " ");
        }
    }

希望可以帮助到小伙伴们~~~

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值