本文中,约定物品个数为 (n),背包的最大价值为 (m)。
多重背包问题的转化
- 可以通过把一个多重背包中的物品拆成多个 (01) 背包中的物品(每次大小翻倍,最后余下的单独拆出一个物品)。插入一个物品的复杂度为 (O(m imes log m))。比较好写,较常用。
- 可以使用单调队列来优化 ( ext{DP}),插入一个物品的复杂度为 (O(m))。比较难写,卡常时用。
完全背包的特殊性质
- 对于物品集合 (A) 和物品集合 (B),(A igcup B) 的完全背包就等于 (A) 的完全背包和 (B) 的完全背包合并的结果。
- 如果有多个大小相同的物品,肯定是取价值最大的物品最优。
任意背包的通用思路
- 合并两个背包的时间复杂度是 (O(m^2)),而加入一个物品的复杂度是 (O(m)) 左右。于是解决问题时,我们尽量避免合并两个背包。
- 如果只计算每种体积是否可以达到,可以用 ( ext{bitset}) 进行常数优化。
- 如果计算方案数,背包可以删除物品,否则不行。
例题试炼
例题一:
(q) 个询问。每次问区间 ([l, r]) 的完全背包。强制在线。
(n, q le 10^5, m le 30)。
线段树维护区间大小为 (k (1 le k le m)) 的最大价值,对于每个询问做完全背包即可。时间复杂度 (O(n imes log n imes m + q imes m^2))。
例题二:
询问对于 (1 le i le n),除了第 (i) 个物品以外的物品的 (01) 背包。
(n, m le 3000)。
分治,递归到左半边时加入右半边的物品,递归到右半边时加入左半边的物品。时间复杂度 (O(n imes log n imes m))。
例题三:
一棵树,每个点都是物品。(q) 次询问,每次询问两点路径 (01) 背包。
(n, q le 10^5, m le 30)。
直接树上倍增需要合并背包,效率低下。考虑点分治,对于 ( ext{DFS}) 只需加单个物品,处理询问时只需合并两个背包。时间复杂度 (O(n imes log n imes m + q imes m^2))。