- BC20260025's blog
背包问题 笔记
- 1 year ago @
0-1背包
题面
有 个物品和一个容量为 的背包,每个物品有重量 和价值 两种属性。要求:选若干个物品放入背包,使背包中物品的总价值最大,且背包中物品的总重量不超过背包的容量 。
分析
设 为在只能放前 个物品的情况下,容量为 的背包所能达到的最大总价值。
考虑转移。假设当前已经处理好了前 个物品的所有状态,那么对于第 个物品,当其不放入背包时,背包剩余容量不变,背包中物品总价值也不变,故这种情况的最大价值为 ;当其放入背包时,背包的剩余容量会减小 ,背包中物品的总价值会增大 ,故这种情况的最大价值为 。
由此可以得出状态转移方程:
这里如果直接采用二维数组对状态进行记录,会出现 MLE。可以考虑改用滚动数组的形式来优化。
由于对 有影响的只有 ,可以去掉第一维,直接用 来表示处理到当前物品时背包容量为 的最大价值,得出以下方程:
代码
核心代码
例题代码
完全背包
题面
有 种物品和一个容量为 的背包,每种物品有重量 和价值 两种属性。要求:选若干个物品放入背包,使背包中物品的总价值最大,且背包中物品的总重量不超过背包的容量 。
分析
设 为在只能放前 个物品的情况下,容量为 的背包所能达到的最大总价值。
考虑一个朴素的做法:对于第 件物品,枚举其选了多少个来转移。这样做的时间复杂度是 的。
状态转移方程如下:
考虑做一个简单的优化。可以发现,对于 ,只要通过 转移就可以了。因此状态转移方程为:
理由是当我们这样转移时, 已经由 更新过,那么 就是充分考虑了第 件物品所选次数后得到的最优结果。换言之,我们通过局部最优子结构的性质重复使用了之前的枚举过程,优化了枚举的复杂度。
与 0-1 背包相同,我们可以将第一维去掉来优化空间复杂度。如果理解 0-1 背包的优化方式,就不难明白压缩后的循环是正向的。
代码
例题代码
不开 long long 见祖宗
多重背包
题面
分析
多重背包也是 0-1 背包的一个变式。与 0-1 背包的区别在于每种物品有多个,而非一个。
一个很朴素的想法就是:把「每种物品选 次」等价转换为「有 个相同的物品,每个物品选一次」。这样就转换成了一个 0-1 背包模型,套用上文所述的方法就可已解决。状态转移方程如下:
时间复杂度 。
二进制分组优化
考虑优化。我们仍考虑把多重背包转化成 0-1 背包模型来求解。
解释
显然,复杂度中的 部分无法再优化了,我们只能从 处入手。为了表述方便,我们用 代表第 种物品拆分出的第 个物品。
在朴素的做法中, , 均表示相同物品。那么我们效率低的原因主要在于我们进行了大量重复性的工作。举例来说,我们考虑了「同时选 」与「同时选 」这两个完全等效的情况。这样的重复性工作我们进行了许多次。那么优化拆分方式就成为了解决问题的突破口。
过程
我们可以通过「二进制分组」的方式使拆分方式更加优美。
具体地说就是令 分别表示由 个单个物品「捆绑」而成的大物品。特殊地,若 不是 的整数次幂,则需要在最后添加一个由 个单个物品「捆绑」而成的大物品用于补足。
举两个例子:
显然,通过上述拆分方式,可以表示任意不大于 个物品的等效选择方式。将每种物品按照上述方式拆分后,使用 0-1 背包的方法解决即可。
时间复杂度
实现
代码
例题代码
混合背包
题面
有 种樱花树和长度为 的时间,有的樱花树只能看一遍,有的樱花树最多看 遍,有的樱花树可以看无数遍。每棵樱花树都有一个美学值 ,求在 的时间内看哪些樱花树能使美学值最高。
分析
混合背包就是将前面三种的背包问题混合起来,这种题目看起来很吓人,可是只要领悟了前面几种背包的中心思想,并将其合并在一起就可以了。
实现
核心代码
例题代码
分组背包
题面
分析
这种题怎么想呢?其实是从「在所有物品中选择一件」变成了「从当前组中选择一件」,于是就对每一组进行一次 0-1 背包就可以了。
再说一说如何进行存储。我们可以将 表示第 组的第 件物品的编号是多少,再用 表示第 组物品有多少个。
实现
这里要注意:一定不能搞错循环顺序,这样才能保证正确性。
有依赖的背包
题面
金明有 元钱,想要买 个物品,第 件物品的价格为 ,重要度为 。有些物品是从属于某个主件物品的附件,要买这个物品,必须购买它的主件。
目标是让所有购买的物品的 之和最大。
分析
考虑分类讨论。对于一个主件和它的若干附件,有以下几种可能:只买主件,买主件 + 某些附件。因为这几种可能性只能选一种,所以可以将这看成分组背包。
如果是多叉树的集合,则要先算子节点的集合,最后算父节点的集合。
小优化
根据贪心原理,当费用相同时,只需保留价值最高的;当价值一定时,只需保留费用最低的;当有两件物品 且 的价值大于 的价值并且 的费用小于 的费用时,只保留 。
变式
输出方案数
输出方案其实就是记录下来背包中的某一个状态是怎么推出来的。我们可以用 表示第 件物品占用空间为 的时候是否选择了此物品。然后在转移时记录是选用了哪一种策略(选或不选)。
求最优方案数
对于给定的一个背包容量、物品费用、其他关系等的问题,求装到一定容量的方案总数。
这种问题就是把求最大值换成求和即可。
例如 0-1 背包问题的转移方程就变成了:
初始条件:
因为当容量为 时也有一个方案,即什么都不装。
A1273 货币系统