动态规划算法求解背包问题

本文介绍了使用动态规划算法解决背包问题的方法,通过实例解释了如何设计二维数组并逐步填充以找到最大价值的物品组合。算法实现包括初始化二维数组,两层循环遍历,并针对浮点数背包问题进行了讨论。
摘要由CSDN通过智能技术生成

问题描述

假设有一个背包,它的最大承重为Nkg(N是整数),现有k个物品T1, T2, …,Tk,它们的重量分别为G1, G2, …Gk.它们的价格分别为P1, P2, …,Pk.
问如何把这些物品装进背包(不能超过背包的承重),使得背包里的物品价格最高?最高价格是多少?

分析

假设
为了简单理解,我们取N=4,共有三件物品,运动鞋,电饭锅和电风扇.它们的重量分别是1kg, 4kg, 3kg,价值分别是150, 300, 200元.

动态规划的思想是设计一个二元函数dp,它返回的是当前条件下的最优解.然后我们可以设计一个二维数组,根据dp的递推公式逐一地向这个二维数组里填值,当我们填完这个二维数组以后,最后填进去的值就是我们要求的最终的结果.
上面是动态规划算法的一个简单概括,其实它的思想就是把一个大问题分解成若干个小问题,每个小问题我们都得到它的一个最优解,也就是局部最优解,再通过寻找小问题到大问题的递推关系,实现局部最优到整体最优的递进.因此如何找到这个关系,或者说,如何规定这样的二元函数,成了我们解决此问题的关键.
从问题的描述我们可以得知,这个解跟物品的重量,背包的承重,以及物品的价值有关,所以在设计dp数组的时候是否就可以利用到其中两个因素作为这个二元函数的两个自变量呢?因为物品的价值是在前两个变量的确定的前提下才可以确定的,所以取前两个作为dp的自变量,对这个自变量我们需要做点适当的改变,使得它易于计算机理解.

数学化这个问题

我们将各种商品编号,正如问题描述的那样,当我们称呼这个商品时,采用编号代替它原本的名字,比如第i个商品,我们把商品编号作为dp函数的第一个自变量,第二个自变量是背包的承重,我们可以把这个背包的承重从小到大排,即从1kg开始,每次递增1kg,直到达到真正的背包承重(这也就是把问题分解成若干个子问题的思想),可以认为每个承重表示一个背包,但最后一个背包才是我们题目中的背包.
根据这样设计的二维数组如下所示:
在这里插入图片描述这样的话dp[i][j]它表示的就是利用第j个背包来装从第1个商品到第i个商品中的任意商品组合时,它们的最大价值.比如第1行第1列就是说如果包的容量为1kg,商品只有一个运动鞋,那么它显然是可以装到背包里去的(这里我们又发现,其实没有必要将重量从1开始,只要从最轻的那个物品重量开始递增就可以了),所以填的是这个运动鞋的价值150,
因为后面的背包容量比它大,所以显然也能装下,因此后面的列里所填的数字都是150.
在这里插入图片描述

假设这些东西的重量和价格都被用以数组表示,weight = {1, 4, 3},value = {150, 300, 200},背包的承重(容量)contain_weight = {1, 2, 3, 4}.显然我们是出于这样的考虑:我们选择的物品的集合S应当满足重量不超过此时的contain_weight[j],也就是 ∑ t ∈ S w e i g h t [ t ] ⩽ c o n t a i n _ w e i g h t [ j ] \sum_{t\in S} weight[t]\leqslant contain\_weight[j] tSweight[t]contain_weight[j],并且 d p [ i ] [ j ] = m a x { ∑ t ∈ S v a l u e [ t ] } dp[i][j] = max\{\sum_{t\in S} value[t]\} dp[i][j]=max{ tSvalue[t]}.当我们要对dp[i][j]赋值时,我们就要考虑一个包含商品i的集合,这个集合要满足上面两个表达式.如果第一个不满足,也就是这个商品超过了背包的承重,那么无论是什么样的包含这个商品的集合都不可能被装入背包中,此时我们也不能不填,但这个时候所谓的最大的物品价值就是不包含这个商品i的了,此时我们的最大价值就应该是dp[i-1][j],也就是上一行的数据粘贴下来就可以了,这种情况一般不会出现.但也要考虑到.
一般不等式1是满足的,那么就存在这样的物品集合 S i S_{i} Si(它表示这个物品集合一定包含i这个物品),接下来就考虑如何实现价值最大化,在此之前,我们最大化的价值是dp[i-1][j],它对应的物品集合我们不清楚,但一定不包含商品i,我们需要找到这样的物品集合 S i S_{i} Si跟前面dp[i-1][j]对应的物品集合没有什么必然联系,这个商品集合 S i S_{i}

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值