1.四边形优化
m(i, j)状态方程满足:
i < j :m(i, j) = MIN {m(i, k-1) + m(k, j) + w(i, j) }
i = j: 0
i > j: INF
对于i <= i' < j <= j' 有 w(i, j) + w(i', j') <= w(i, j') + w(i', j) 则m(i, j) + m(i', j') <= m(i, j') + m(i', j) 即为满足四边形定理
令s(i, j)为对应决策变量的最大值,即m(i, j)通过s(i, j)达到最优, 并且s(i, j)最大
s(i, j) = MAX(i<k<=j) {m(i, j) = m(i, k-1) + m(k, j) + w(i, j) }
如果m(i, j)满足四边形定理, 则s(i, j) <= s(i, j+1) <= s(i+1, j+1)
于是m(i, j) = MIN(s(i, j-1) <= k <= s(i+1, j)) {m(i, k-1) + m(k, j) + w(i, j) }
2.斜率优化
此处以dp(i) = MIN{fun(k)}为例, MAX时相似
k<j<i,当计算dp(i)时, 如果j 比 k优, 则fun(j) < fun(k),化简可得
(y(j)-y(k)) / (x(j)-x(k)) < f(i)
令g(j, k) = (y(j) - y(k)) / (x(j) - x(k))
如果g(j, k) < f(i) 说明计算i时j比k更优。如果g(i, j) < g(j, k) 则j不会成为最优解
我们假设g(i, j) < f(i), 那么就是说i点要比j点优, 排除j点
如果g(i, j) >= f(i), 那么j点此时是比i点要更优, 但是同时g(j, k) > g(i, j) >= f(i)这说明还有k点会比j点更优, 同样排除j点
于是对于斜率优化做法可以总结如下:
1, 用一个单调队列来维护解集
2, 假设队列中从头到尾已经有元素a b c。那么当d要入队的时候,我们维护队列的上凸性质,即如果g(d, c)<g(c, b),那么就将c点删除。直到找到g(d, x)>=g(x, y)为止,并将d点加入在该位置中
3,求解时候,从队头开始,如果已有元素a b c,当i点要求解时,如果g(b, a) < f(i),那么说明b点比a点更优,a点可以排除,于是a出队。最后dp(i) = getDp(q[head])
3.单调队列优化
单调队列是一种严格单调的队列,可以单调递增,也可以单调递减。队首位置保存的是最优解,第二个位置保存的是次优解,ect。。。
单调队列可以有两个操作:
1、插入一个新的元素,该元素从队尾开始向队首进行搜索,找到合适的位置插入之,如果该位置原本有元素,则替换它。
2、在过程中从队首删除不符合当前要求的元素。
单调队列实现起来可简单,可复杂。简单的一个数组,一个head,一个tail指针就搞定。复杂的用双向链表实现。
用处:
1、保存最优解,次优解,ect。
2、利用单调队列对dp方程进行优化,可将O(n)复杂度降至O(1)。也就是说,将原本会超时的N维dp降优化至N-1维,以求通过。不是任何DP都可以利用单调队列进行优化呢
记住!只有形如 dp[i]=max/min (f[k]) + g[i] (k<i && g[i]是与k无关的变量)才能用到单调队列进行优化。
优化的对象就是f[k]。