# DP优化
动态状态
一个转移只用到很小的一部分状态,则不断刷新状态,使得其只与我需要的同阶。
例题:P3188 [HNOI2007] 梦幻岛宝珠
前缀和优化
就是枚举的值存下来,以防止重复的枚举。
例题:2024.10.3T3 Kanade的水杯60分
路径化DP
将一个二维的、仅仅是在相邻位置进行转移的DP看作条从初始状态到目标状态的路劲,接着用一些路径的方法进行优化。
-
网格图路径问题的分治做法
例题:2024.10.1T4
-
通过路径的转移方案算起始状态的贡献
例题:Game on Sum (Hard Version)
贡献反推
如果一组DP的终点状态相同、方程相同,但是初始状不同,可以考虑DP终止状态对初始状态的贡献。
具体的方法是将原DP的方程反过来,即a→b变为b→a,最好画图理解。
例题:2024.10.9T3粒子对撞
限制全局化
例题:P3349 [ZJOI2016] 小星星,2024.10.10T4 计数题
在“小星星”中,通过容斥将恰好为集合S变为了至多为集合S,前者需要在每个节点存储一个状态,而后者不用。
在“计数题”中,通过强制根节点的选择,将一个限制全局化,从而不用存在每个状态中。
随机游走
对于一类具有“体积”有正负并最终回到0点的DP问题,我们可以将所有物品打乱,根据“随机游走”的理论,其期望不会走出V的距离,所以最终就将OV优化为V,最好开到2n,否则容易被卡。
例题:P7606 [THUPC2021] 混乱邪恶
未来状态
状态为未来的情况,存储统计过去的点在未来的情况下的贡献,并随着范围的扩大,使得未来的情况减少,有点像“势能”减少。
例题:P8916 [DMOI-R2] 暗号
整体修改
如果对于大量的状态,在转移的时候都有相同的修改(比如说加上,乘上复制成同一个值),那么可以直接使用线段树等数据结构上进行整体修改
例题:ARC073F Many Moves
所有情况的贡献之和
对于一个计数DP而言,如果一个转移所贡献的系数与一个状态a有关,且最终的答案是计算所有状态a的贡献之和。那么可以专门去记录这一状态的和,以达到统一转移的效果。
例题:2024.10.18T2击球手,2024.10.3T1 Mafuyu 的作业,P1654 OSU!
状态拼凑
如果对于状态A,难以直接进行转移,可以将其拆分为B,C两个易于转移的状态,最后再合起来凑出原状态。
例题:2024.10.16T4 Z
非子树树形DP
-
DFN序DP
方法:设dpi表示考虑时间戳小于等于i的所有节点的情况。
优势:将子树的所有节点放在一起
例题:优化树上依赖性背包:P6326 Shopping
参考:DP 优化小技巧
-
欧拉序DP
方法:设dpi,s表示考虑欧拉序小于等于i的所有节点,其中欧拉序为i的点x到根节点的选择情况为j时的信息。
优势:相邻的两个位置只有向上与向下两种,在于每次是添加叶子节点,往往只需要考虑者单个节点的贡献,而传统的子树DP可以看作添加根合并多棵树,往往需要考虑合并子树的复杂度,在合并复杂度高(比如背包)或不能合并的时候考虑。
劣势:由于需要从下还原回上面,所以需要记录到根节点的所有点的状态。导致带一个O(2^dep)的复杂度。常常需要考虑如何减小树高。
例题:P3577 [POI2014] TUR-Tourism(题目限制树高),2024.11.13T3 冒险家
值域定义域互换
条件:最值DP,状态很大,所存储的值却很小。在所有去到相同值的状态,只关注其中的一个,且可以转移。
做法:将值作为状态,关心的状态作为值。
例题:[AGC033D] Complexity,P3537 SZA-Cloakroom
做差法
- 单调递增差分
特殊性质:要求所选元素单调递增,或者说有着一个使值单增的影响。
做法:只考虑与上一个数的差,形如下图
例题:P2481 代码拍卖会,P7519 滚榜,U526032天各一方
- 做差后值域减小
条件:值域很大,但真正合法的很少,与另一个变量的差后很小。
方法:做差。
例题:CF744C Hongcow Buys a Deck of Cards,P4590 [TJOI2018] 游园会
CDQ优化DP
对于那种两两做出转移,且转移的条件与i,j都有关系
例题:P5979 [PA2014] Druzyny,U498421 切序列
更改枚举顺序
一种顺序下的变化性很强,可换种枚举顺序后,就诞生了新的“定值”,新的性质。
例题:CF1310C Au Pont Rouge
线性最值贡献优化DP
比如有方程fi=mink(fi-wk+ak,gi),我们可以直接,fi=minfi-w,gi,复杂度变为O(n)。
例题:T470003 颜桉_c
状压线性化
条件:有状压解法,并且转移规则不受代表集合影响。
做法:纵向考虑每个元素在不同状态下做的贡献的累加,因为不同集合转移不受影响,这里无须枚举各个集合,往往可以将复杂度从O2n优化为On。
例题:2024.11.07T2 string
例题解释:这道题首先设了一个c_i 表示当前节点需要经过的次数,这样就把不断走的过程转化成了对每个节点贡献的考虑,于是对一个节点考虑的时候,去掉走其他节点的过程,只考虑当前节点需要往左/右走的次数的变化,进行DP。
最后发现对于所有节点,其实最优概率只与往左右走的需求次数有关,直接做一次处理即可,答案就是在所有节点转移的最后概率的乘积。
与最值之差
DP的值存放成与最劣/最优情况的差的最值,就是考虑什么时候取不到最优/最劣值。
例题:动态规划_李奕辰A - Paint
不存储不影响决策的信息
有效影响:即可以导致后面的决策发生变化的影响。对于一个状态,我们只应该存储状态中的有效状态。
例题:2024.11.8T3 广告(这道题中T型的那个单独的位置若不与前面联通,其状态就不必保留)
贪心降维
-
贪心背包
适用对象:体积很大的背包
方法:选择性价比最大的那个贪心去凑到一个与目标状态相近的值,其他的物品选择的数量不会超过性价比最大的那个物品体积的平方(抽屉原理可证)。
例题:P9140 [THUPC 2023 初赛] 背包(同余最短路)P8392 Uplifting Excursion(先贪心再DP)
-
贡献的增速大于线性
特殊性质:贡献的增长十分迅速,导致某一维增大到一定范围后就一定不优,从而减少状态范围。
例题:P9676 [ICPC 2022 Jinan R] Skills
-
贪心向需求值靠拢以减少范围
例题:2025.2.20T2 Sum