[学习笔记]决策单调性优化 DP

引入

  • 一类最优化 DP:

  • [f_i={min/max}_{j=0}^{i-1}{f_j+w(j+1,i)} ]

  • 利用 (w) 的特殊性质,可以做到 (O(nlog n))(O(n)) 的复杂度

第一类

特殊性质

  • (f_i) 的最优决策为 (p_i),则对于任意 (i<j)(p_i<p_j)

优化方法一

  • 考虑对于每个未计算出的 (f),维护其最优决策

  • 即每算出一个 (f_j),就把那些取决策 (j) 更优的 (f_i) 的最优决策更新成 (j)

  • 由定义可知,需要更新决策的 (i) 一定是一段后缀

  • 考虑用一个栈维护决策序列,对于每个决策 (j) 维护一个区间 ([l,r]) 表示 (f_{ldots r}) 的最优决策为 (j)

  • (f_j) 计算出来的时候,先考虑栈顶的 (l),考查 (f_j) 能否更新 (f_i) 的最优决策

  • 如果能就弹栈顶继续检查

  • 否则在栈顶的区间 ([l,r]) 中二分出一个最小的 (i) 满足 (f_i) 能被 (f_j) 更新最优决策

  • (r) 改成 (i-1),并把决策 (j) 压入栈,区间为 ([i,n])

  • (O(nlog n))

优化方法二

  • 上面的方法存在一定的局限性:(w(j+1,i)) 必须能快速求出来

  • (w(j+1,i)) 必须以 (O(i-j)) 的复杂度求出时,考虑另一种实现方式:分治

  • 定义分治函数 solve(l, r, xl, xr) 表示 (f_{ldots r}) 的决策在 ([xl,xr]) 之间

  • (mid=lfloorfrac{l+r}2 floor),求出 (f_{mid}) 的最优决策 (m)

  • 然后递归到 solve(l, mid - 1, xl, m)solve(mid + 1, r, m, xr)

  • 还是 (O(nlog n))

  • 需要注意实现姿势,避免复杂度爆炸,保证单次分治的复杂度为 (O(r-l+xr-xl))

  • 但这种优化方法也有局限性:转移必须是 (g ightarrow f) 而不能是 (f ightarrow f),即转移不能进行在同一个数组内

  • 常用于分层 DP 中

第二类

特殊性质

  • (w(j,i+1)-w(j,i))(w(j+1,i+1)-w(j+1,i)) 的大小关系对于所有的 (i,j) 都一样,即满足四边形不等式

  • 换句话说,对于任意的两个决策 (j<k),存在一个 (x) 满足 (ile x)(j)(k) 优,(i>x)(j)(k)

  • 或者 (ile x)(j)(k) 劣,(i>x)(j)(k)

优化方法

  • (ile x)(j)(k) 优,(i>x)(j)(k) 劣,则这和前面提到的第一类是等价的,可以直接用第一类的优化方法

  • 但这里讲述另一种方法

  • 考虑维护一个单调队列,储存对当前的 (i)(i) 之后可能最优的决策

  • 每当计算出一个 (f_l) 之后,检查队尾的两个决策 (j,k) 是否会因为决策 (l) 的加入而使得 (k) 变成不可能最优的决策

  • 根据定义里提到的特殊性质,我们只需二分出一个最大的 (i) 满足决策 (k)(l) 优,然后判断这时 (j) 是否比 (k) 优,是则 (k) 应该被从队尾弹出

  • 这样一直弹栈直到 (k) 可能最优为止

  • 考虑取 (f_i) 最优决策,可以证明去除了无用的决策之后,队列内剩下的决策对应 DP 值是单峰的,故从队首不断出队即可找到最优决策

  • (O(nlog n))

  • 实际上判断是否弹队尾,有时可以使用特殊的方法代替二分来实现 (O(1)) 判断

  • 如斜率优化的本质就是这种形式的决策单调性优化

  • (ile x)(j)(k) 劣,(i>x)(j)(k) 优,则最优决策要从队尾取,这时把队列改成栈即可

原文地址:https://www.cnblogs.com/xyz32768/p/13055420.html