0-1背包问题(动态规划)

本文详细介绍了如何使用动态规划解决0-1背包问题,包括明确dp数组的含义、确定递推公式、初始化dp数组、遍历操作及打印结果。通过一个具体的例子,解释了动态规划在背包问题中的应用,最后给出了Python代码实现,包括一维数组的滚动优化版本。

0-1背包是典型的动态规划问题,同时也是秋招笔试和面试常考问题,所以必须解决,其他公众号或者博客都写到,解决动态规划问题,要遵循以下步骤进行考虑:
1、明确dp数组的下标含义
2、确定递推公式
3、dp数组初始化
4、遍历序列
5、打印dp数组
我们可以先假设一个例子:
背包的最大重量为 4
物品为:
| |重量 | 价值
|物品0| 1 | 15
|物品1| 3 | 20
|物品2| 4 | 30
第一步,明确dp数组的下标含义,使用二维数组dp[i][j], 即dp[i][j] 表示从下标为[0-i]的物品⾥任意取,放进容量为j的背包,价值总和最⼤是多少。一定要明确dp数组的下标含义,要不以后会越来越蒙圈, 建议可以画一个如下的表格
在这里插入图片描述

第二步 确定递推公式
可以有两个⽅向推出来dp[i][j],明确任务这个物品放不放到背包之中
(1)如果物品 不满足条件 既物品不放到背包中。 由dp[i - 1][j]推出,即背包容量为j,⾥⾯不放物品i的最⼤价值,此时dp[i][j]就是dp[i - 1][j]
(2)物品要放到背包中,由dp[i - 1][j - weight[i]]推出,dp[i - 1][j - weight[i]] 为背包容量为j - weight[i]的时候不放物品i的最⼤价值,那么dp[i - 1][j - weight[i]] + value[i] (物品i的价值),就是背包放物品i得到的最⼤价值

所以递归公式: dp[i][j] = max(dp[i - 1][j], dp[i - 1][j - weight[i]] + value[i])

第三步:dp数组初始化
1、如果背包的重量为0, 则任何物品都放不到背包中
在这里插入图片描述
2、由递推公式可知,dp[i][j] 都是由dp[i-1]推导而来,所以需要明确dp[i-1]的值,既需要先定义表格中第一行的数据,也就是物品0放入背包中的value.
在这里插入图片描述
python代码如下:

dp = [[0] * (bagweight+1) for i in range(len(weight))]
for j in range(weight[0],bagweight+1, 1):
    dp[0][j] = value[0]

第四步,遍历顺序
由dp数组肯定双循环,可以先遍历物品,然后遍历背包, 也可以先遍历背包,然后物品。我是按照先遍历物品,然后背包的顺序:

for i in range(1, len(weight)):
    for j in range(bagweight+1):
        if (j < weight[i]): dp[i][j] = dp[i-1][j]
        else:
            dp[i][j] = max(dp[i-1][j], dp[i-1][j - weight[i]] + value[i])

第五步 打印dp数组
可以按照上一步的递推顺序,把数据依次填入上面的表格中,加深理解
在这里插入图片描述
python完整代码如下:

#物品重量和价值
weight = [1, 3, 4]
value = [15, 20, 30]
#背包重量
bagweight = 4 
#初始DP数组
dp = [[0] * (bagweight+1) for i in range(len(weight))]
for j in range(weight[0],bagweight+1, 1):
    dp[0][j] = value[0]
    
#开始循环
for i in range(1, len(weight)):
    for j in range(bagweight+1):
        if (j < weight[i]): 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[len(weight) - 1][bagweight])

Python补充代码,使用一维数组(滚动数组):

weight = [1, 3, 4]
value = [15, 20, 30]
bagweight = 4
#初始DP数组
dp = [0 for i in range(bagweight+1)]
#开始循环(注意下面这俩for循环不能颠倒,不信自己试试看)
for i in range(len(weight)):
    for j in range(bagweight, weight[i] -1, -1):
         dp[j] = max(dp[j], dp[j-weight[i]] + value[i])
print(dp[bagweight])
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值