动态规划——背包问题【完全背包】

问题描述:

  有N种物品和一个容量为V的背包,每种物品都有无限件可用。第i种物品的费用是w[i],价值是v[i]。求解将哪些物品装入背包可使这些物品的费用总和不超过背包容量,且价值总和最大。


贪心 Y or N ?
  因为每件物品都可以选取任意件,你也许会想到贪心算法:选取价值最高的就好了~~~ 看上去没什么毛病,但是有一个问题,就是往往无法填满背包,还有剩余空间。当然,你也许会想:用价值第二高的填充,如果还是放不下,就选第三、四高的填充。听起来似乎可行,但是很容易举出反例:两个物品:A(价值5,体积5)、B(价值8,体积7),背包大小为10。那么用上述贪心算法,只能选取一个B物品,获得价值为8。但是很明显,正解为10。所以贪心算法在这里并不适用。


最优化原理
  假设完全背包的最优解为F(n1,n2,…,nN)(n1,n2 分别代表第1、第2件物品的选取数量),完全背包的子问题为,将前i种物品放入容量为t的背包并取得最大价值,其对应的解为:F(n1,n2,…,ni),假设该解不是子问题的最优解,即存在另一组解F(m1,m2,…,mi),使得F(m1,m2,…,mi) > F(n1,n2,…,ni),那么F(m1,m2,…,mi,…,nN) 必然大于 F(n1,n2,…,nN),因此 F(n1,n2,…,nN) 不是原问题的最优解,与原假设不符,所以F(n1,n2,…,ni)必然是子问题的最优解。


无后效性:
  对于子问题的任意解,都不会影响后续子问题的解,也就是说,前i种物品如何选择,只要最终的剩余背包空间不变,就不会影响后面物品的选择。即满足无后效性。

因此,完全背包问题也可以使用动态规划来解决。


定义dp[ i ][ j ]:在前 i 件物品中选取物品,放到容量为 j 的背包所获得的最大价值。
状态转移方程: dp[ i + 1 ][ j ] = max ( dp[ i ][ j - k * w[ i ] ] + k * v[ i ] );
因为完全背包中,第 i 个物品可以选多次,上式中的 k 就代表这个次数。 由于上式左边背包最大容积为 j ,所以 k 最大最大不能超过 j / wi; 故 k 的范围是 0<= k <= j / wi。
这个式子很直观,甚至01背包也可以用这个式子表示,只要把 k 的取值范围改正{0, 1},也就是说,其实01背包是一种特殊的完全背包。虽然得出这个结论不难,但是如果这个式子的效率不高,做了很多重复的计算。
所以我们给出新的状态转移方程:
dp[ i + 1 ][ j ] = max ( dp[ i ][ j ] , dp[ i + 1 ][ j - w[ i ] ] + v[ i ] )


下面证明二者等价:
dp[ i + 1][ j ]= max( dp[ i ][ j ] , dp[ i+1 ][ j - wi ] + vi )
      = max (dp[ i ][ j ] , max { dp[ i ][ j- wi - k * wi ]+k *vi } +vi ), k>=0
      = max ( dp[ i ][ j ] , max{ dp[ i ][ j- k * wi ]+k * vi } ), k>=1
      = max{ dp[ i ][ j - k * wi ] + k *vi },k>=0


算法分析:

在这里插入图片描述
首先我们在i,j位置时

  • 如果不拿第 i 个物品,那么dp为②
  • 如果拿第 i 个物品,那么dp为③

那么考虑,为什么不需要①位置? 这是因为,纵向严格单调非递减。
那么这样一来,循环次序也就固定了,只能从小到大更新。


完全背包空间压缩

将空间压缩至一维:
 for(int i = 0; i < n; i++){
   for(int j = 0; j <= V; j++){
     dp[ j ] = max( dp[ j ], dp[ j - w[ i ] ] + v[ i ] );
   }
 }

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值