背包问题

  • 背包有最大承重,商店中的每种物品都有价值与重量两个属性,基于此提出各种问题:装下最多重量物品、装下最大总价值物品、有多少种方式正好带走满满一书包物品等等。

 

  • Backpack,最简单的题型是背包中的物品能不能拼出重量target,求出最大的target,背包问题中,数组大小与总承重有关背包问题要把总承重放入状态!这是很特殊的一个地方。要求前N个物品能不能拼出重量0,1,...,M,子问题是需要知道前N-1个物品能不能拼出重量0,1,...,M,由此得出状态f[i][w] =  能否用前i个物品拼出重量w(true/false)。转移方程如下:

 

                  

               

 

  • Backpack5,题目改成有多少种方式拼出target,要求前N个物品有多少种方式拼出重量0,1,...,targer,需要知道前N-1个物品有多少种方式拼出重量0,1,...,target,状态设f[i][w] = 用前i个物品有多少种方式拼出重量w,转移方程如下:

               

 

这里提出了一种空间优化的方法,基于原有的思路,可以开辟一个两行的数组进行优化,当采用从后往前的方式进行计算时,不会出现覆盖的情况,所以这里可以进一步优化。代码:

 

         

 

  • Backpack6,与上面题目的区别是每个重量可以重复用多次,这里需要回到一维的思路,类似于Coin Change,这里的最后一步是枚举如果最后一个物品的重量是A0,...An-1,则要求有多少种组合能拼成Target - A0,..Target - An-1,状态是f[i] = 有多少种组合能拼出重量i,转移方程如下:

 

                   

这里的边界情况要注意一下,如下:

 

          

 

       

 

  • Backpack2,背包有最大承重,每个商品有着各自不同的价值,求背包中能放入的最大价值的物品。如果对于每个总重量,我们能知道对应的最大价值是多少,就能通过一个for循环找出答案,所以这里的状态也是从总承重的角度考虑(即重量作为数组下标,价值作为数组元素),当然也会存在某些重量拼不出来的情况,可以设为无穷小。对于背包问题,最后一步的考虑方式有两种:最后一个物品是否进入背包,以及最后进入背包的物品是哪一个!这里在实际编程时使用了一维数组进行空间优化,需要注意的是当使用一位数组时,要从后往前做,倒着计算。状态和转移方程如下:

 

                   

初始条件和边界情况:

 

         

 

核心代码:

 

               

 

  •  Backpack3,与上一题的区别在于每种物品都有无穷多个。从性价比的角度考虑,由于物品不能切割,所以不能使用贪心算法进行计算。状态和转移方程可以根据上一题时进行修改,即最后一个物品进入背包几次,如下:

 

                 

 

通过画矩阵以及距离分析的方法,目标是能否减少枚举过程中的重复计算,简化之后的转移方程如下:

 

        

 

对于数组空间的优化,通过观察转移方程中计算的顺序,可以将一个二维问题降至一维求解,只不过这里与上面一题的区别在于计算顺序可以从前往后了,代码的修改也是只需要修改计算顺序那一部分。

 

 

 

           

 

 

 

 

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值