01背包问题

十分感谢这位大大的讲解!
http://blog.csdn.net/liuqiyao_01/article/details/8521776

接下来为个人对01背包问题的理解:

每种物品数量均为1,每个物品都包含体积weight和价值value,而有一个Weight大小的背包,怎么装才能让这个背包里的总价值Value最大

首先,我们可以有下面这段代码:
dp[i][j]=max(dp[i-1][j],dp[i-1][j-weight[i]]+value[i]);

i为当前选取第i个物品,j为体积。
那么dp[i][j]的含义为,不选取这件物品(dp[i-1][j])和选取这件物品(dp[i-1][j-weight[i]]+value[i])的最大值。

后面选取这件物品可能有些难理解,我们解析一下。

这个j为什么是个变量?
因为当你选取了一个物品时,背包的体积就会改变为Weight-weight[i],所以从0(背包为满)到Weight(背包为空)这些都是可能发生的情况。

而这个dp[i-1][j-weight[i]]是什么含义?
当你选取了第i个物品,你需要将这个物品的weight[i]从j中减去,j-weight[i]就是当前剩余的体积,dp[i-1][j-weight[i]]就是选取第i个物品之前的(j-weight[i])的最大价值。

这两个难点搞定了之后,我们就有了下面的代码:

for(i=1;i<=n;i++)
    for(j=0;j<=Weight;j++)
        if(j>=weight[i])
            dp[i][j]=max(dp[i-1][j],dp[i-1][j-weight[i]]+value[i]);
        else
            dp[i][j]=dp[i-1][j];

当选取第n个物品,背包大小为Weight的情况下,总价值的最大值就是dp[n][Weight]了。

注意这里采用的是二维数组,但我们可以用一维数组来节省空间。

for(i=1;i<=n;i++)
    for(j=Weight;j>=weight[i];j--)
            dp[j]=max(dp[j],dp[j-weight[i]]+value[i]);

注意到j的循环从正序变为倒序,原因是当j从大到小时,较小的j仍保存的是上一次循环的值,使用时相当于dp[i-1][j-weight[i]],若改为顺序的话,较小的j被更新为dp[i][j-weight[i]],与原来的顺序不符。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值