背包问题的总结
Daniel_yuan · · 个人记录
与背包相关的动态规划问题
在整个动态规划问题中,背包问题的占比是相当大的。
从刚学 OI,到冲刺 HNOI,都可以找到与当前水平相对应的背包题目(虽然可能套了一些别的东西)。
故在此记录一些有关背包的技巧。
多重背包
对于多重背包,有两种优化,一种是单调队列,一种是二进制分组。前者的复杂度是
两者各有千秋,从复杂度上看,前者是更优的,但是在变式上的实用性上看,后者更加有用。因为后者相当于把问题转化成了一个 01 背包的问题,而有些算法仅适用于 01 背包。
具体的,二进制分组是把一个有
多重背包的小 trick 1
有这么一个例题:你有一个背包,容量为
乍一看是个 01 背包,不过这样的话复杂度是
多重背包的小 trick 2 \& 3
有这么一个例题:你有一个背包,容量为
首先可以观察到价值很小,花费很大。所以对于这种类型的背包,可以考虑把 DP 状态反过来:设
不过对于这道题而言,复杂度还是很高,考虑继续优化。刚开始学习背包的时候,可能会有贪心的想法,即优先选择单位价格最低的物品,选到不能选了再选第二低的物品……以此类推,不过这个算法在当时是个错误的算法,因为选择物品会使背包容量“变小”,这是有后效性的,但是这个思想可以用到这个题目里面来。可以发现,如果物品
即两个 trick:交换状态,贪心优化。
同余最短路
有这么一个例题:你有三种物品,每种物品的数量无穷大,每种物品的花费是分别是
给这种题目归个类:每种物品可以用无限多次,不过每个物品的花费比较小,要判断一个很大的
直接跑背包显然炸掉了,因为容量太太太太太大了。考虑怎么优化,可以发现一旦达到了
分层背包
有这么一个例题:你有一个背包,容量为
给这种题目归个类:每种物品的花费满足某个特殊条件,要跑一个很大的背包。
直接跑背包显然炸掉了,因为容量和花费都太太太太太大了。不过可以发现花费都可以分解成一个比较小的数乘上一个
树形背包
总是有出题人喜欢把序列上的题目出到树上,让选手强行处理树上问题。这种行为已经很无趣了。 —— 佚名
有的题目做着做着就上了树。 —— 佚名
树形依赖背包
有这么一类题目:如果要选择某个物品,那么必须先选择另一个物品,且把所有限制看成连边,最终会形成一个外向树森林,这类即是树形依赖背包。
树形依赖背包的 DP 状态十分显然:设
一种较为普通的合并是把一个点的所有子树在该点合并,并且每次枚举到总容量
这样显然不优,有两种优化。均可以优化到
一种优化是基于 DFS 序的。先把整棵树的 DFS 序拿出来,然后在 DFS 序上 DP,那么就有
一种优化是进入子树的时候,把当前节点的 DP 值赋值下去且强制把它儿子选了,最后遍历一遍出来后,这个子树的 DP 值就是选择了这个儿子的 DP 值,那么还有一种情况就是不选即原 DP 数组,所以最后两个 DP 数组取
花费为 1 普通树形背包
有一种人尽皆知的优化卡上界的方法,就是每次只枚举到
但是如果背包容量只有
考虑证明,一种不是那么严谨的证明是,在父亲节点处
另一种更为严谨的证明是分四种情况讨论,假设需要合并的是
-
size_u\geq m,size_v\geq m 一次合并的复杂度为
O(m^2) 。考虑所有的极小的size \geq m 的子树(即它里面的所有子树的size 都小于m ),显然它们两两不相交,所以至多有\frac{n}{m} 个。此外,这种情况会出现,当且仅当:u 已经合并过的儿子里有极小的子树,并且v 里面有极小的子树。故而合并的次数为极小的子树个数- 1 。故而这一部分的复杂度是O(m^2\times \frac{n}{m})=O(n\times m) -
size_u\geq m,size_v<m 这种情况的复杂度是
O(m\times size_v) ,我们考虑求\sum size_v 的上界。对于每一个点考虑,它的祖先中,满足size_x<m 且size_{fa_x}\geq m 的点至多只有一个,所以会出现这种情况的(u,v) 至多只有一个,所以\sum size_v=O(n) ,所以这种情况的总复杂度是O(n\times m) 。 -
size_u<m,size_v \geq m 类似地我们考虑求
\sum size_u 的上界。具体证明同上,故size_u=O(n) ,故复杂度是O(n\times m) 。 -
sz_u<m,size_v<m 这个时候就是普通的树形背包,对于一整棵大小为
x 的树我们知道这样的复杂度是O(x^2) 。考虑所有的、极大的size < m 子树(即满足size_{fa_x} \geq m ),每一个这样的子树的复杂度是O(m^2) ,而这样的子树两两不相交,所以至多有\frac{n}{m} 个,所以总复杂度为O(m^2 \times \frac{n}{m})=O(n\times m) 。
综上,时间复杂度是
参考自 这里 。