01背包问题的遍历与循环顺序理解

01背包问题中遍历与循环顺序理解

问题说明

在01背包问题中,需要对背包和物品进行遍历。是先对背包进行遍历,还是先对物品进行遍历,亦或者二者都可以?那遍历的顺序是正序还是倒序呢,也就是说从前往后遍历还是从后往前遍历呢?

答案解释

01背包问题中有两种常见的解法,一种是一般的二维dp数组解法,另一种是状态压缩后的一维dp数组解法。针对不同的解法,上述问题的答案也不相同,下面分情况讨论。

二维dp数组

这种解法比较常规,也比较易于理解,具体的核心思路为:
定义dp[i][j],含义为前i个物品在容量为j的背包中的最大价值。dp[i][j]的状态来源有两种:第一种是不放入第i个物品,则说明前i-1个物品已经达到了容量j,因此dp[i][j]=dp[i-1][j];第二种是放入第i个物品,则说明前i-1个物品的容量为j-weight[i],因此dp[i][j]=dp[i-1][j-weight]+value[i];因为我们需要价值最大,所以dp[i][j]=max(dp[i-1][j],dp[i-1][j-weight]+value[i])

j=0j=1j=2j=3j=4
i=000000
i=105555
i=205111616
i=305111620

我们根据迭代公式可以看到,求取dp[i][j]时我们需要的仅仅是第i-1行的0~ j列的数据。因此我们判断遍历顺序时,就需要看哪种顺序可以在求取dp[i][j]时其第i-1行的0~j列已经求完。我们发现无论是先遍历物品(按行求取),还是先遍历背包容量(按列求取),都可以满足上述要求,同时正序和倒序都满足上述要求。
所以针对这种解法,任何顺序都可以。

一维dp数组

一维dp数组就是把二维数组而状态压缩,定义dp[j],迭代公式为dp[j]=max(dp[j],dp[j-weight[i]]+value[i])
相对于求取dp[i][j]后把dp[i-1][j]的位置给替换了,这样相当于节省了空间。但是求取dp[i][j]时需要用到第i-1行的0~j列,如果正序求取的话,第i-1行的0 ~ j列(左上方)的数据就已经被替换了,所以求解错误,如果倒序求取dp[i][j]的话,第i-1行的0 ~ j列(左上方)的数据还没有被替换,因此求解正确。
知道了需要倒序求解后,我们再看是先遍历物品还是先遍历背包容量,如果先遍历背包容量(按列求取),且需要倒序,我们发现求取dp[i][j]时,其第i-1行的0 ~ j列(左上方)的数据还没有被求取,因此不能先遍历背包容量。先遍历物品(按行求取)时,即使是倒序,第i-1行的0 ~ j列(左上方)的数据也已经被求取,因此我们需要先遍历物品,且需要是倒序!

总结

当我们采用状态压缩的方法来求解背包问题时,可以列出上述表格,按照以上分析思路来观察求解顺序,从而判断遍历与循环顺序。

  • 3
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值