背包与背包型DP
定义
- 狭义的背包问题是常见的选物品。
- 广义的背包问题指一种特殊DP状态设计:
- DP状态的一维表示选择的量。
- 题目对该量有限制。例如,常见的量有:
- 已选物品的个数。
- 已进行操作的代价。
常见背包类型
- 01背包
- 完全背包
- 多重背包
- 树上背包
常见处理方法
通用技巧
- 一些剪枝:
- 将一定不选的物品直接去掉(价值关于体积必须递增)。即若对于物品 和 ( 的体积 小于 的体积 ),且 ( 表示价值),则物品 可直接去掉。
- 将DP状态设成“恰好”,用
vector存状态,将不优的状态去掉(dp值关于体积必须递增)。绝大多数题目出题人都不会卡(卡不掉)这个做法,可以放心使用。 - 将体积相同的物品合并处理,可能是直接删掉,或是排序处理(因为转移只与体积有关)。
- 二进制分组:
- 可将物品数量降为 个。
- 用于处理多重背包或完全背包。
- 折半搜索:处理 在 左右的问题。
- 合并和插入的转化(优化状态或转移):
- 插入转合并(较常用):
- 条件:合并复杂度更优。
- 处理:结合分治/倍增实现。
- 例子:
- 倍增FFT。
- 分治 + 闵可夫斯基和。
- 合并转插入:
- 条件:
- 插入复杂度更优。
- 需特别注意插入顺序的影响。
- 处理:可能结合启发式实现。
- 例子:树上连通块DP的启发式做法。
- 条件:
- 插入转合并(较常用):
- 性价比背包:
- 将物品按价值与体积的比 排序后选择。
- 可保证总体积为某个前缀和时,其价值和最优。
- 处理存在性背包:
- 存在性完全背包(同余最短路):
- 实现:转圈实现。
- 复杂度:最小的物品体积 * 体积种数 ,即 。
- 存在性多重背包(bitset):
- 复杂度:本质不同的转移数 * 背包容量 ,即 。
- 进制分解的结论(特殊存在性01背包):
- 物品按体积 从小到大排序后,满足 。
- 那么在上下界之间的任何一个容量 ,都能通过类似进制分解的方法构造出解。
- 例题:ARC LIS on tree 2。
- 存在性完全背包(同余最短路):
- 处理计数背包:
- 背包合并:利用多项式卷积FFT/NTT,即通过计算两个多项式的卷积来合并背包。设两个背包对应的多项式为 和 ,则它们的卷积 。
- 可删除背包(回退背包):
- 适用范围:类似高维前缀和/01背包方案数那样的数值DP转移(最优化不行)。
- 经典例题:
- 消失之物:带回退的01背包。
- solution:略。
- 题目:给定数组 ,每次询问给定 ,问 中选 个数的乘积期望是多少。两个方案不同当且仅当 个数的下标组成的集合不同,。
- solution:莫队加上回退背包即可。
- 处理最优化背包:
- 体积小的多重背包处理(普通增函数和凸包合并):
- 按体积分组后,同一体积内为 问题。
- 按总体积对当前体积的余数,转移可分成若干类,每类互不干扰。
- 观察价值函数,有明显凸性,可猜测具有决策单调性。注意,DP数组本身无凸性。
- 例题:Jewel Thief。
- 带凸性的背包合并(凸包合并):利用闵可夫斯基和。对于两个凸多边形 和 ,它们的闵可夫斯基和 。
- 带凸性的背包求恰 个物品:使用wqs二分。
- 体积小的多重背包问题通法(复杂度与背包容量无关):
- 贪心 + 小范围dp:
- 适用范围:任意背包,(物品数量),(物品体积),(物品价值)可负。
- 具体做法:
- 先将体积为负的物品默认选上,然后将其体积和价值取反,使所有体积变为正。
- 先用性价比背包尽量接近限制容量 。
- 之后需删一些已选物品并添加一些未选物品,用多重背包实现,背包容量为 ,其中 是最大的体积。
- 对背包容量的证明:
- 首先,尽量接近后的体积与限制容量的差 $ \lt w$。
- 最终的背包体积与限制容量的差也 $ \lt w$。
- 中间调整过程存在一种方案,使当前体积与限制容量的差始终 $ \lt w$。
- 由于性价比背包的最优性,任何一种总体积在调整过程中最多被遍历一次(否则调整后会更优)。
- 所以最多选 个物品增加体积, 个物品减少体积,背包容量为 。
- 例题:Uplifting Excursion。
- 贪心 + 小范围dp:
- 体积小但容量较大的完全背包处理:(不是通解,对容量下界有限制)
- P9140 [THUPC 2023 初赛] 背包
- 通解:与普通完全背包结合,可实现总复杂度 。
- 体积小的多重背包处理(普通增函数和凸包合并):
可能用到的结论
- 总体积一定时,不同的体积数是根号级别的:
- proof:利用根号分治可证。
- 这表明,有容量限制(和限制)时通常满足根号分治的前提条件,难点在于设计算法。
- 物品体积正负都有,总体积恰好是 ,绝对值最大的物品体积为 :
- 存在一种调整物品放置顺序的方法,使任何时候的体积都在 中,其中 满足 ,且 , 均在 中 。
- proof:对于当前体积 ,若下一个体积使 越过范围,不妨设 (超过下界 ),此时必然存在一个正体积的物品,使用该物品可使 。
- 需注意,这不能直接通过朴素的背包DP实现,因为要求特定顺序。
- 物品体积有正负,物品价值均为正时,最优解不会重复经过同一个总体积:
- 特别地,若是多重背包,可将负价值物品先钦定必选从而转成正价值。
- proof:显然。
- 注意,同余最短路、最优化多重背包的做法都用到了这个结论的变体。
- 物品体积有正负,最终体积和为恰 的01背包:
- 过程中可取背包最大容量为 。
szzjz WiKi