1、01背包

 

一、课程目标

  1. 背包问题
  2. 01背包
  3. 动态规划
  4. 过程理解
  5. 关键代码

二、目标详解

1、背包问题

基本模型:一个容量为V的背包,在一定的限制条件下,放进最多(或最少)价值的东西。

根据限制条件的不同,分为三种情况:

  • 01背包(ZeroOnePack):每种物品只有一件,即只能选择放或者不放
  • 完全背包(CompletePack):每种物品有无限件
  • 多重背包(MultiplePack):每种物品最多有n[i]件可用

2、01背包动态规划

基本模型:一个容量为V的背包与N件物品,第i件物品的体积是c[i],价值为w[i],求将哪些物品装入背包可使得价值总和最大。

维度为:i件物品、j容量的背包

定义状态:设dp[i][j]表示把i件物品放入容量j的背包可获得的最大价值。

对于第i件物品(体积为c[i],价值为w[i]):

  • 不放到背包里,则最大价值为dp[i-1][j]
  • 放到背包里,则最大价值为dp[i-1][j-c[i]] + w[i]

状态转移方程为:

  • 初始化:dp[0][j] = 0, dp[i][0] = 0
  • j < c[i]:dp[i][j] = dp[i-1][j]
  • j>=c[i]:dp[i][j] = max(dp[i-1][j], dp[i-1][j-c[i]] + w[i])

3、理解过程

假设背包容量V=8,物品数量N=4:

物品编号1234
体积c2345
价值w3456

3.1 第一步:初始化

  • dp[i][0]和dp[0][j]都为0
  • 前两列体积c和价值w,为方便查询
cwi\j012345678
--0000000000
2310 
3420 
4530 
5640 

3.2 第二步:怎么填?

  • 1的列:由于1 < c[1](体积为2)所以dp[1][1] = dp[1-1][1] = 0
    • 同样,dp[2][1]、dp[3][1]、dp[4][1]等都是0
  • dp[1][2]:由于2==c[1], dp[1][2]=max(dp[1-1][2], dp[1-1][2-2] + 3) = 3
    • 理解:把1物品放进去,体积为2,获得价值为3
  • dp[2][2]:由于2<c[2], dp[2][2] = dp[2-1][2] = 3
    • 理解:2物品放不进去,所以还是只能放一个1物品
  • ….依次类推到dp[1][3]、dp[1][4]…、dp[1][8] 都为3
cwi\j012345678
--0000000000
231003333333
342003 
453003 
564003 

3.3 第三步:dp[2][3]

dp[2][3] = max(dp[2-1][3], dp[2-1][3-c[2]]+w[2])=max(3, 0+4)=4

  • 理解:物品1或物品2都可以放进去,选择价值大的:
  • 物品2放进去,则剩余容量为0,为dp[1][0] + w[2]=4
  • 物品2不放进去,为dp[1][3]=3
cwi\j012345678
--0000000000
231003333333
3420034
453003 
564003 

dp[2][3]更直观的理解:

  • 如果放进去
    • 本列第一行的3,减去本行的体积列(c[i]),结果为0
    • 找到上一行的0列的值,值为0
    • 0加上本行的价值列(w[i]),结果为4
  • 如果不放进去:取上一行的本列的,值为3
  • dp[2][3]填写4和3的最大值4

3.4 最后结果,按以上理解逐步填写

cwi\j012345678
--0000000000
231003333333
342003447777
453003457899
5640034578910

最后,dp[4][8] = 10

4、关键代码

for(int i=1; i<=N; i++)
for(int j=1; j<=V; j++) {
  if(j >= c[i])
    dp[i][j] = max(dp[i-1][j], dp[i-1][j-c[i]] + w[i]);
  else
    dp[i][j] = dp[i-1][j];
}

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值