背包问题个人小结

背包问题

基本背包问题

问题描述

有n件物品(序号为i),每件体积为v[i], 物品价值c[i],现有一个容积为m的背包
问这个背包能塞下的最大价值是多少

问题分析

这个问题是比较经典的动态规划问题,当n值较大时,穷举每件物品放不放入背包的情况是非常多的
构造方程f[i][j]表示前i个物品+容器为j的背包能装下的最大价值

由此构建转移方程
f[i][j] = max(f[i-1][j], c[i] + f[i-1][j-[v[i]]])

理解这个方程:
假设我们已知f[x][y]的所有值时(x<i y<=j),为此我们求值f[i][j]
我们可以将f[i][j]视作f[i-1][j]变化而来的,也就是我们在可选的物品里增加了一个物品
由此我们可以有两种选择

  • 不将物品放入背包, 此种情况相当于没有添加心物品,此时的最大价值为f[i-1][j]
  • 将该物品放入背包,此时背包里已有了v[i]体积,并且我们手中有了c[i]的价值
    而在此同时,我们还有一个容器还剩j-v[i]的背包,此时背包剩余容积能装下的最大价值就是f[i-1][j-v[i]]
    再将这个值加上我们最先放到背包里的新添加的物品的价值,就得出了此种情况下的最大价值f[i-1][j-v[i]+c[i]

在这个切入点除了这两种情况,还有别的没考虑的情况吗?没有
好,那么这两种情况各自的最大价值较大的那个就是前i件物品用容积为j的背包所能装下的最大价值,即f[i][j] = max(f[i-1][j], c[i] + f[i-1][j-[v[i]]])

小结

快滚去写代码

完全背包问题

问题描述

在基本背包问题的基础上,不限制每个物品的数量

问题分析

构造方程f[i][j]表示前i个物品+容器为j的背包能装下的最大价值
仍然将f[i][j]视作从f[i-1][j]状态变化而来,即新添加了一个物品

沿用前面的判断

由此我们可以有两种选择
- 不将物品放入背包, 此种情况相当于没有添加心物品,此时的最大价值为f[i-1][j]
- 将(一件)该物品放入背包,此时背包里已有了`v[i]`体积,并且我们手中有了`c[i]`的价值
而在此同时,我们还有一个容器还剩`j-v[i]`的背包,此时背包剩余容积能装下的最大价值就是`f[i-1][j-v[i]]`
再将这个值加上我们最先放到背包里的新添加的物品的价值,就得出了此种情况下的最大价值`f[i-1][j-v[i]+c[i]`

在这个切入点除了这两种情况,还有别的没考虑的情况吗?
这次有,不但有,还很多

  • 放入2件新添加的物品
  • 放入3件新添加的物品
  • 放入4件新添加的物品
  • 放入5件新添加的物品
  • 放入n件新添加的物品 (当n*v[i] < j 背包放得下)

之前我们求的是两种情况最大价值中的最大值,这次我们求(n+1)种情况最大价值的最大值
此外当我们放入第一件新增物品时,如果这时的最大价值小于不放的情况
这说明我们的这件物品价值很低了,没必要在尝试再放两件甚至更多,可以减少计算次数

转移方程

此时的转移方程

f[i][j] = max(
    f[i-1][j],
    1*c[i] + f[i-1][j-1*v[i]],
    2*c[i] + f[i-1][j-2*v[i]],
    3*c[i] + f[i-1][j-3*v[i]],
    ....
    n*c[i] + f[i-1][j-n*v[i]],
)

小结

还不滚去写代码

多重背包

问题描述

在完全背包的基础上,每个物品不是1个也不是无穷多个
而是若干个,而且每个物品的数量可以不同

问题分析

你看懂了前面几个,这题做不出来,你都对不起我
在完全背包问题中,我们尝试将新添加物品从放入1个到放入n个
在多重背包问题中,我们将新添加物品从放入1个到放入x个(x为该物品数量)

转移方程

此时的转移方程

f[i][j] = max(
    f[i-1][j],
    1*c[i] + f[i-1][j-1*v[i]],
    2*c[i] + f[i-1][j-2*v[i]],
    3*c[i] + f[i-1][j-3*v[i]],
    ....
    x*c[i] + f[i-1][j-x*v[i]],
)

小结

滚去写代码啊啊啊啊啊啊!!!

混合背包

问题描述

混合背包就是基本背包,完全背包,多重背包的缝合怪
每个背包的数量可以为1个,x个,无穷多个

问题分析

解每个f[i][j]的时候,根据物品的数量选择就完事了,就是个if else的事情

小结

写啊写啊写代码

二维背包

问题描述

在前面问题的基础上,新引入另一个资源限制重量
w[i]表示每个物品的重量, 然后一个背包不但有容积x,还有重量限制y

问题分析

现在方程f[i][j]已经不满足我们的需求了,不过没关系,多加一维的问题,小事情
好了,新的方程为f[i][j][k] 表示容积为j,重量上限为k的背包装前i个物品的最大价值

状态转移方程

为避免将问题复杂话,咱们仅将二维背包和基本背包结合起来

f[i][j][k] = max(f[i-1][j][k], c[i]+f[i-1][j-v[i]][k-w[i]])

看懂了吗,还是那个模式,将新增物品放入还是不放入,放入一个还是多个

小结

你是已经是一个成熟的程序员里,应该不要让人催,自己就该赶紧去写代码

分组背包问题

问题描述

在基本背包问题的基础上将物品分为若干组,每组物品中仅能选择1个物品放入背包中

好了,我们这次又要改方程
f[g][i][j]表示用容积为j的背包在前g组装前i个物品的最大价值

状态转移方程

f[g][i][j] = max(f[g-1][i][j], f[g-1][i-1][j-v[i]])

小结

懂?

华为机试练习题

分组背包+小变化

相当于将物品划分了若干组,每组物品个数为1~3个,其中1个为主物品,放该组内其他物品前必须将该物品放入背包,否则不能放

问题分析

还是沿用分组背包的方程

状态转移方程

# x, y, z表示第g组的各个物品的序号,第一个为主物品
x, y, z = fenzu[g]
f[g][i][j] = max(
    f[g-1][i][j],   # 第g组物品一个不放
    w[x]+f[g-1][i][j-v[x]],   # 只放主物品
    w[x]+w[y] + f[g-1][i][j-v[x] - v[y]], # 放主物品+附件1
    w[x]+w[z] + f[g-1][i][j-v[x] - v[z]], # 放主物品+附件2
    w[x]+w[y]+w[z] + f[g-1][i][j-v[x]-v[y]-v[z]] # 放主物品+附件3
)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值