DP
DP
非常重要的一部分知识!
这里根据一般 OI 中的习惯把一些递推也称作 DP 了。
基础理论
使用 DP 解决问题,我们首先将问题划分成若干「阶段」,将子问题的特征抽象成「状态」,进而推导出状态的所有可能「决策」,设计出状态转移方程。
无后效性是 DP 有正确性的前提。
背包问题
非常经典的 DP 问题。
01 背包
\(n\) 个物品,每个物品有重量和价值两个属性,问一个给定容量上界 \(V\) 能得到的最大物品价值总和。
因为太典了就不展开了,时间复杂度 \(O(nV)\)。
完全背包
和 01 背包的区别在于每个物品可以选无限次。
转移顺序倒过来就行了,时间复杂度 \(O(nV)\)。
多重背包
和 01 背包的区别在于每个物品有一个选择次数上界。
朴素的实现考虑将物品拆开,把问题变成 01 背包,复杂度 \(O(V\sum num_i)\)。
二进制分组优化可以将复杂度优化成 \(O(V\sum \log_2 num_i)\)。
单调队列优化可以将复杂度优化成 \(O(nV)\)。(下文单调队列优化再具体展开)
单调队列优化
远古的回忆!
我们试图刻画单调队列优化的能力范围。
对于一个状态的转移顺序,如果其决策区间单调移动,更可能作为最优状态转移的状态可以被我们使用单调队列维护,优化决策复杂度。
以单调队列优化多重背包为例回顾一下这个方法。
朴素的转移方程形如:\(f_{i,j}=\max_{k=0}^{num_i}(f_{i,j-kw_i}+kv_i)\)。
我们考虑将模 \(w_i\) 的同余类 \(c\) 拿出来观察转移方程:
\(f_{i,c+jw_i}=\max_{k=0}^{j}(f_{i,c+kw_i}+(j-k)v_i)\)
这明显满足决策区间单调移动的性质,我们使用单调队列优化,对于一个物品复杂度 \(O(\lfloor\dfrac{V}{w_i}\rfloor\times w_i)=O(V)\),总复杂度 \(O(nV)\)。
斜率优化
感觉是提高组时期的噩梦。
能力范围大致是优化形如这样的转移方程:
\(f_i=\min_{j<i}(P_i\times Q_j+A_i+B_j)\)
我们将 \((Q_j,B_j)\) 放在二维平面上考虑,相当于我们需要找到的决策点是斜率为 \(-P_i\) 的直线从下往上第一次切到凸包的决策点。
- \(Q_i\) 单调,\(P_i\) 单调
双端队列维护凸壳即可。 - \(Q_i\) 单调,\(P_i\) 不单调
仍然双端队列维护凸壳,凸壳上二分找到最优决策点。 - \(Q_i\) 不单调
使用平衡树维护凸壳。
经玄燕提醒,使用李超树维护更为简单。
决策单调性
四边形不等式狗都不推。OI 不需要证明,拍出来是对的就行了!(
基本定义
区间包含单调性:称一个函数 \(w(l,r)\) 满足区间包含单调性,当且仅当 \(\forall l\le x\le y\le r,w(x,y)\le w(l,r)\)。
四边形不等式:称一个函数 \(w(l,r)\) 满足四边形不等式,当且仅当 \(\forall l_1\le l_2\le r_1\le r_2,w(l_1,r_1)+w(l_2,r_2)\le w(l_1,r_2)+w(l_2,r_1)\),即交叉小于等于包含。
2D1D
结论是对于形如 \(f_{l,r}=\min_{k=l}^{r-1}(f_{l,k}+f_{k+1,r})+w(l,r)\) 的方程,如果 \(w(l,r)\) 满足区间包含单调性和四边形不等式,那么 \(f\) 有决策单调性。
具体的,记 \(p_{l,r}\) 表示 \(f_{l,r}\) 的最优决策点,\(p_{l,r-1}\le p_{l,r}\le p_{l+1,r},l+1<r\)。
这将解决问题的复杂度降至了 \(O(n^2)\)。
分治法、二分栈与环上邮局
凸优化
也不一定和 DP 结合在一起,也能 MST 之类的,博主不是很懂凸啊,可能是因为数学不太行。
对于形如恰好 \(k\) 个的限制,如果关于 \(k\) 的函数 \(f\) 是凸的,\(f(i)-f(i-1)\ge f(i-1)-f(i-2)\) 或者符号取反,我们考虑一条直线去切这个函数,斜率单调变化的过程中,切点也在单调变化,故我们可以做 wqs 二分。
杂项
- 交换 DP 值域与状态
对于值域很小的情况,我们通过这样的手段降低复杂度。 - 容斥简化状态
容斥是一种有力的手段,帮助我们模糊掉状态,一个经典的例子是 小星星。