斜率优化dp学习

转自orzzz 斜率优化dp学习

用了一堂半的课才彻底搞懂。其他神犇写的博客或多或少有点小bug,所以orzzz不才斗胆重新写一个。

里面大量穿用其他神犇的原话,就不逐一标明出处了。

引用资料 Accept的博客 MathonL的博客

 

斜率优化dp学习_第1张图片

 

首先是最经典的题的题面。

HDU 3507,很适合的一个入门题。

大概题意就是要输出 N N N个数字 a [ N ] a[N] a[N],输出的时候可以连续连续的输出,每连续输出一串,它的费用是 “这串数字和的平方加上一个常数 M M M”。

我们设 d p [ i ] dp[i] dp[i]表示输出到 i i i的时候最少的花费, S [ i ] S[i] S[i]表示从 a [ 1 ] a[1] a[1] a [ i − 1 ] a[i-1] a[i1]的数字和。注意这里为了方便起见前缀和与一般的有区别。

则有: d p [ i ] = m i n { d p [ j ] + ( S [ i + 1 ] − S [ j ] ) 2 + M } dp[i]=min \left\{ dp[j]+(S[i+1]-S[j])^2+M \right\} dp[i]=min{dp[j]+(S[i+1]S[j])2+M}

复杂度显然是 O ( n 2 ) O(n^2) O(n2)的。对于 500000 500000 500000 n n n显然过不了。那么我们想,能否在 O ( 1 ) O(1) O(1)时间内找到所有转移里最优的那个呢?
我们假设在求解 d p [ i ] dp[i] dp[i]时,存在 j , k j,k j,k 使得从 j j j转移比从 k k k转移更优,那么需要满足条件: d p [ j ] + ( S [ i + 1 ] − S [ j ] ) 2 + M < d p [ k ] + ( S [ i + 1 ] − S [ k ] ) 2 + M dp[j]+(S[i+1]-S[j])^2+Mdp[j]+(S[i+1]S[j])2+M<dp[k]+(S[i+1]S[k])2+M
展开上式
d p [ j ] + S [ i + 1 ] 2 − 2 S [ i + 1 ] S [ j ] + S [ j ] 2 + M < d p [ k ] + S [ i + 1 ] 2 − 2 S [ i + 1 ] S [ k ] + S [ k ] 2 + M dp[j]+S[i+1]^2-2S[i+1]S[j]+S[j]^2+Mdp[j]+S[i+1]22S[i+1]S[j]+S[j]2+M<dp[k]+S[i+1]22S[i+1]S[k]+S[k]2+M
移项并消去再合并同类项得
d p [ j ] − d p [ k ] + S [ j ] 2 − S [ k ] 2 < 2 S [ i + 1 ] ( S [ j ] − S [ k ] ) dp[j]-dp[k]+S[j]^2-S[k]^2<2S[i+1](S[j]-S[k]) dp[j]dp[k]+S[j]2S[k]2<2S[i+1](S[j]S[k])
S [ j ] − S [ k ] S[j]-S[k] S[j]S[k]除过去,得到

d p [ j ] − d p [ k ] + S [ j ] 2 − S [ k ] 2 S [ j ] − S [ k ] < 2 S [ i + 1 ] \frac{dp[j]-dp[k]+S[j]^2-S[k]^2}{S[j]-S[k]}<2S[i+1] S[j]S[k]dp[j]dp[k]+S[j]2S[k]2<2S[i+1]

我们设 f [ x ] = d p [ x ] + S [ x ] 2 f[x]=dp[x]+S[x]^2 f[x]=dp[x]+S[x]2,就化成了

f [ j ] − f [ k ] S [ j ] − S [ k ] < 2 S [ i + 1 ] \frac{f[j]-f[k]}{S[j]-S[k]}<2S[i+1] S[j]S[k]f[j]f[k]<2S[i+1]

即当 ( j < k ) (j(j<k)时,若KaTeX parse error: Expected 'EOF', got '&' at position 28: …[k]}{S[j]-S[k]}&̲lt;2S[i+1],则 j j j对更新 d p [ i ] dp[i] dp[i] k k k更新 d p [ i ] dp[i] dp[i]优。

休息一下qwq。这个东西好像斜率。

当一个数的 d p dp dp值求完了,它的 f f f值也跟着确定,我们就可以在空间中绘制出点 ( S [ i ] , f [ i ] ) (S[i],f[i]) (S[i],f[i])。这个点代表已经求出 d p dp dp值的一个点。

当我们要求解 d p [ t ] dp[t] dp[t]时,如果可用的集合里存在这样三个点,位置关系如图所示:

斜率优化dp学习_第2张图片

那么显然

f [ j ] − f [ k ] S [ j ] − S [ k ] > f [ i ] − f [ j ] S [ i ] − S [ j ] \frac{f[j]-f[k]}{S[j]-S[k]}>\frac{f[i]-f[j]}{S[i]-S[j]} S[j]S[k]f[j]f[k]>S[i]S[j]f[i]f[j]
这时候他们和 2 S [ t + 1 ] 2S[t+1] 2S[t+1]的关系有3种:
f [ j ] − f [ k ] S [ j ] − S [ k ] > f [ i ] − f [ j ] S [ i ] − S [ j ] > 2 S [ t + 1 ] \frac{f[j]-f[k]}{S[j]-S[k]}>\frac{f[i]-f[j]}{S[i]-S[j]}>2S[t+1] S[j]S[k]f[j]f[k]>S[i]S[j]f[i]f[j]>2S[t+1]

那么 j j j i i i优, k k k j j j优。
f [ j ] − f [ k ] S [ j ] − S [ k ] > 2 S [ t + 1 ] > f [ i ] − f [ j ] S [ i ] − S [ j ] \frac{f[j]-f[k]}{S[j]-S[k]}>2S[t+1]>\frac{f[i]-f[j]}{S[i]-S[j]} S[j]S[k]f[j]f[k]>2S[t+1]>S[i]S[j]f[i]f[j]
那么 i i i j j j优, k k k j j j优。
2 S [ t + 1 ] > f [ j ] − f [ k ] S [ j ] − S [ k ] > f [ i ] − f [ j ] S [ i ] − S [ j ] 2S[t+1]>\frac{f[j]-f[k]}{S[j]-S[k]}>\frac{f[i]-f[j]}{S[i]-S[j]} 2S[t+1]>S[j]S[k]f[j]f[k]>S[i]S[j]f[i]f[j]
那么 i i i j j j优, j j j k k k优。
综上,不管什么样的 S [ t + 1 ] S[t+1] S[t+1],从 j j j转移都不会是最佳方案。那么用一个数据结构维护一个凸包(下凸),每加入一个点就删去一些点,使其维持凸包的形态。最优转移一定在这个凸包中。
但还是不能 O ( 1 ) O(1) O(1)对吧。在凸包里,谁又是最最优呢?
首先一定数据结构里的凸包一定会是这样的:

斜率优化dp学习_第3张图片

假设 j i → \overrightarrow{ji} ji 的斜率KaTeX parse error: Expected 'EOF', got '&' at position 1: &̲gt;2S[t+1] k j → \overrightarrow{kj} kj 的斜率KaTeX parse error: Expected 'EOF', got '&' at position 1: &̲lt;2S[t+1]从图形特点我们可以发现 j j j点比所有比 k k k小的点都优,比所有比 i i i大的也优。所以对于我们二分查找斜率比 2 S [ t + 1 ] 2S[t+1] 2S[t+1]小的编号最大的点,就是最优的转移点。由于 S [ i ] S[i] S[i]也满足单调性,我们还可以直接维护一个单调队列就能解决这个问题。
推广一下,如果不等式右侧不是像 S [ i + 1 ] S[i+1] S[i+1]这样的单调函数,二分就好了。
所有小于等于的情况我都没提,想一想就知道了。重要的是思想啊对不对~

你可能感兴趣的:(动态规划)