「算法笔记」背包问题解题思路

本文中,约定物品个数为 \(n\),背包的最大价值为 \(m\)

多重背包问题的转化

  1. 可以通过把一个多重背包中的物品拆成多个 \(01\) 背包中的物品(每次大小翻倍,最后余下的单独拆出一个物品)。插入一个物品的复杂度为 \(O(m \times \log m)\)。比较好写,较常用。
  2. 可以使用单调队列来优化 \(\text{DP}\),插入一个物品的复杂度为 \(O(m)\)。比较难写,卡常时用。

完全背包的特殊性质

  1. 对于物品集合 \(A\) 和物品集合 \(B\)\(A \bigcup B\) 的完全背包就等于 \(A\) 的完全背包和 \(B\) 的完全背包合并的结果。
  2. 如果有多个大小相同的物品,肯定是取价值最大的物品最优。

任意背包的通用思路

  1. 合并两个背包的时间复杂度是 \(O(m^2)\),而加入一个物品的复杂度是 \(O(m)\) 左右。于是解决问题时,我们尽量避免合并两个背包。
  2. 如果只计算每种体积是否可以达到,可以用 \(\text{bitset}\) 进行常数优化。
  3. 如果计算方案数,背包可以删除物品,否则不行。

例题试炼

例题一:

\(q\) 个询问。每次问区间 \([l, r]\) 的完全背包。强制在线。

\(n, q \le 10^5, m \le 30\)

线段树维护区间大小为 \(k (1 \le k \le m)\) 的最大价值,对于每个询问做完全背包即可。时间复杂度 \(O(n \times \log n \times m + q \times m^2)\)

例题二:

询问对于 \(1 \le i \le n\),除了第 \(i\) 个物品以外的物品的 \(01\) 背包。

\(n, m \le 3000\)

分治,递归到左半边时加入右半边的物品,递归到右半边时加入左半边的物品。时间复杂度 \(O(n \times \log n \times m)\)

例题三:

一棵树,每个点都是物品。\(q\) 次询问,每次询问两点路径 \(01\) 背包。

\(n, q \le 10^5, m \le 30\)

直接树上倍增需要合并背包,效率低下。考虑点分治,对于 \(\text{DFS}\) 只需加单个物品,处理询问时只需合并两个背包。时间复杂度 \(O(n \times \log n \times m + q \times m^2)\)

猜你喜欢

转载自www.cnblogs.com/blog-of-xianglingao/p/10409814.html