01背包问题(python模板)

问题概述

有一个背包,最大承重为N,现在要装一些物品i(物品价值为value[i],物品重量为weight[i]),求这个背包装这些物品后的最大价值。

01背包特点

每种物品只有一个,要么选要么不选

01背包(二维数组版本)

分析

  • dp[i][j]表示在背包容量j从i个物品中任选物品的最大价值dp[i][j]
  • 价值全部先为0,考虑到后面有加法运算。第一行价值需要初始化,从第一行可以承受的重量开始到最后,对第一行第一个物品的价值初始化。
  • 如果物品质量大于背包,说明背包放不下,此时最大价值应为dp[i-1][j],即就是上一行同列的价值。同样的空间,但因为放不下,所以最大价值和上一行同列最大价值相等。
  • 如果物品质量小于等于背包,说明背包放得下。现在分为两种情况,即放和不放。
  • 如果不放,当前最大价值为上一行同列价值dp[i-1][j]
  • 如果放,当前最大价值为预留空间最大价值加物品的价值,即dp[i-1][j-weight[i]]+ value[i]
  • 遍历顺序这里任意,无论是先背包还是先物品都可以,习惯上一般先物品,再背包

代码

weight =[1,3,4]
value = [15,20,30] 
Max = 4 # 背包的最大容量

dp = [[0]*5  for i in range(3)] # dp[i][j]表示i物品在j容量中的最大价值

for i in range(weight[0],Max+1):
    dp[0][i] = value[0]


for i in range(1,3): 
    for j in range(1,5):
        if weight[i] > j: # 如果物品质量大于背包,说明放不下
            dp[i][j] = dp[i-1][j] # 和上一行最大价值一致
        else:
            dp[i][j] = max(dp[i-1][j],dp[i-1][j-weight[i]]+ value[i]) 

print(dp)

01背包(一维滚动数组版本)

分析

  • 这里进行了状态压缩,由于我们知道二维数组我们其实只要最后一个值(即右下角的值),所以这耗费了大量的空间,为何我们不能只用一维数组滚动记录呢?
  • dp[j]表示容量为j的背包中的最大质量
  • 最大价值这里,第一个肯定是本身的价值dp[j](其实这里相当于上一行同列的最大价值),以及预留空间价值加物品价值dp[j-weight[i]]+value[i]取最大值。有人可能会觉得不太好理解,其实如果能理解二维数组操作的话,理解一维滚动数组应该不难。假如我第一行滚动完了,第二行初值不就是第一行的数值吗?现在就是我们不用刻意去写上一行,因为上一行和我这行是一样的,所以直接在二维的基础上去掉所有二维的行就可以了。
  • 这里最要注意的一个应该是遍历顺序
  • 我们稍微思考一下,二维数组在操作的时候,由于是用上一行的数据更新本行最大值,所以背包可以用正序遍历,逆序遍历,这都无所谓。但是,一维滚动数组中,背包一定需要逆序进行操作。
  • 一维背包逆序的话,我当前背包最大价值的更新依赖于我前面的背包(由于前面背包还没有更新,所以相当于是用二维数组的上一行数据更新,符合我们刚才说的二维数组的操作)。如果是正序的话,正序背包最大值的更新依赖于前面的背包,前面的背包已经被更新过了,相当于我拿本行的数据进行更新(相当于叠加),某样物品会被重复取,不符合0,1背包!

代码

weight =[1,3,4]
value = [15,20,30] 
Max = 4 # 背包的最大容量

dp = [0]*5 # dp[j]表示背包容量为j的最大价值为dp[j]

for i in range(3):
    for j in range(4,weight[i]-1,-1):
        dp[j] = max(dp[j],dp[j-weight[i]]+value[i])
print(dp)

最后结果

所以容量为4的背包,所能承受的最大价值都是35
在这里插入图片描述

如有错误,敬请指正,欢迎交流,谢谢♪(・ω・)ノ

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值