别担心,斜率优化不是什么很毒瘤的数学知识。
例题
但这 O ( n 2 ) O(n^2) O(n2) 的做法当然不是我们追求的~
斜率优化
这个优化很强,直接把 d p dp dp 优化成 O ( n l o g n ) O(nlogn) O(nlogn) 甚至是 O ( n ) O(n) O(n) 的,所以这几乎是一个算法了。
具体是,我们需要寻找到 d p dp dp 方程中的单调性,发现单调性之后,就可以直接找到最优的那个,直接从它转移过来即可。
那么先写出这个例题的转移方程(数组的定义在朴素做法里面):
f
[
i
]
=
min
j
=
0
i
−
1
{
f
[
j
]
+
t
[
i
]
×
(
c
[
i
]
−
c
[
j
]
)
+
s
×
(
c
[
n
]
−
c
[
j
]
)
}
f[i]=\min\limits_{j=0}^{i-1}\{f[j]+t[i]\times (c[i]-c[j])+s\times (c[n]-c[j])\}
f[i]=j=0mini−1{f[j]+t[i]×(c[i]−c[j])+s×(c[n]−c[j])}
于是开始寻找单调性:假如从
j
j
j 转移到
i
i
i 比从
k
k
k 转移到
i
i
i 更优(且
j
>
k
j>k
j>k),那么需要满足:
f
[
j
]
+
t
[
i
]
×
(
c
[
i
]
−
c
[
j
]
)
+
s
×
(
c
[
n
]
−
c
[
j
]
)
<
f
[
k
]
+
t
[
i
]
×
(
c
[
i
]
−
c
[
k
]
)
+
s
×
(
c
[
n
]
−
c
[
k
]
)
f[j]+t[i]\times(c[i]-c[j])+s\times(c[n]-c[j])<f[k]+t[i]\times(c[i]-c[k])+s\times(c[n]-c[k])
f[j]+t[i]×(c[i]−c[j])+s×(c[n]−c[j])<f[k]+t[i]×(c[i]−c[k])+s×(c[n]−c[k])
展开得:
f
[
j
]
+
t
[
i
]
c
[
i
]
−
t
[
i
]
c
[
j
]
+
c
[
n
]
s
−
c
[
j
]
s
<
f
[
k
]
+
t
[
i
]
c
[
i
]
−
t
[
i
]
c
[
k
]
+
c
[
n
]
s
−
c
[
k
]
s
f[j]+t[i]c[i]-t[i]c[j]+c[n]s-c[j]s<f[k]+t[i]c[i]-t[i]c[k]+c[n]s-c[k]s
f[j]+t[i]c[i]−t[i]c[j]+c[n]s−c[j]s<f[k]+t[i]c[i]−t[i]c[k]+c[n]s−c[k]s
搞一搞:
f
[
j
]
−
t
[
i
]
c
[
j
]
−
c
[
j
]
s
<
f
[
k
]
−
t
[
i
]
c
[
k
]
−
c
[
k
]
s
f
[
j
]
−
c
[
j
]
(
t
[
i
]
+
s
)
<
f
[
k
]
−
c
[
k
]
(
t
[
i
]
+
s
)
f
[
j
]
−
f
[
k
]
<
−
(
c
[
k
]
−
c
[
j
]
)
(
t
[
i
]
+
s
)
f
[
j
]
−
f
[
k
]
c
[
j
]
−
c
[
k
]
<
t
[
i
]
+
s
f[j]-t[i]c[j]-c[j]s<f[k]-t[i]c[k]-c[k]s\\ f[j]-c[j](t[i]+s)<f[k]-c[k](t[i]+s)\\ f[j]-f[k]<-(c[k]-c[j])(t[i]+s)\\ \frac {f[j]-f[k]} {c[j]-c[k]}<t[i]+s\\
f[j]−t[i]c[j]−c[j]s<f[k]−t[i]c[k]−c[k]sf[j]−c[j](t[i]+s)<f[k]−c[k](t[i]+s)f[j]−f[k]<−(c[k]−c[j])(t[i]+s)c[j]−c[k]f[j]−f[k]<t[i]+s
诶?左边很像一个斜率耶。
假如有两个点坐标为 ( c [ j ] , f [ j ] ) , ( c [ k ] , f [ k ] ) (c[j],f[j]),(c[k],f[k]) (c[j],f[j]),(c[k],f[k]),那么左边这个东西就是经过这两点的直线的斜率。
也就是说,假如两个点 j , k j,k j,k 的斜率小于 t [ i ] + s t[i]+s t[i]+s,那么用 j j j 来更新 i i i 比用 k k k 来更新 i i i 更优。
把前面的 i − 1 i-1 i−1 个坐标( c [ j ] , f [ j ] c[j],f[j] c[j],f[j])画出来之后,发现只有这些点形成的下凸包上的点是有用的。
为什么呢?
显然,在最下面、最左边、最右边的点一定在下凸包上,假如我们选一个不在下凸包上的点,那么一定存在另外两个在下凸包上点,与它的位置关系满足下面三个中的一个(设该点为
B
B
B,另外两个在下凸包上的点为
A
A
A 和
C
C
C):



这三种情况有一个共同的特点,也就是
A
B
AB
AB 的斜率大于
B
C
BC
BC 的斜率。
也就是: f [ B ] − f [ A ] c [ B ] − c [ A ] > f [ C ] − f [ B ] c [ C ] − c [ B ] \frac {f[B]-f[A]} {c[B]-c[A]} > \frac {f[C]-f[B]} {c[C]-c[B]} c[B]−c[A]f[B]−f[A]>c[C]−c[B]f[C]−f[B] → \to → f [ C ] − f [ B ] c [ C ] − c [ B ] < f [ B ] − f [ A ] c [ B ] − c [ A ] \frac {f[C]-f[B]} {c[C]-c[B]} < \frac {f[B]-f[A]} {c[B]-c[A]} c[C]−c[B]f[C]−f[B]<c[B]−c[A]f[B]−f[A]
那么 t [ i ] + s t[i]+s t[i]+s 与他们的关系有三种:
-
t
[
i
]
+
s
<
f
[
C
]
−
f
[
B
]
c
[
C
]
−
c
[
B
]
<
f
[
B
]
−
f
[
A
]
c
[
B
]
−
c
[
A
]
t[i]+s < \frac {f[C]-f[B]} {c[C]-c[B]} < \frac {f[B]-f[A]} {c[B]-c[A]}
t[i]+s<c[C]−c[B]f[C]−f[B]<c[B]−c[A]f[B]−f[A]
此时 B B B 比 C C C 优, A A A 比 B B B 优 -
f
[
C
]
−
f
[
B
]
c
[
C
]
−
c
[
B
]
<
t
[
i
]
+
s
<
f
[
B
]
−
f
[
A
]
c
[
B
]
−
c
[
A
]
\frac {f[C]-f[B]} {c[C]-c[B]} < t[i]+s < \frac {f[B]-f[A]} {c[B]-c[A]}
c[C]−c[B]f[C]−f[B]<t[i]+s<c[B]−c[A]f[B]−f[A]
此时 C C C 比 B B B 优, A A A 比 B B B 优 -
f
[
C
]
−
f
[
B
]
c
[
C
]
−
c
[
B
]
<
f
[
B
]
−
f
[
A
]
c
[
B
]
−
c
[
A
]
<
t
[
i
]
+
s
\frac {f[C]-f[B]} {c[C]-c[B]} < \frac {f[B]-f[A]} {c[B]-c[A]} < t[i]+s
c[C]−c[B]f[C]−f[B]<c[B]−c[A]f[B]−f[A]<t[i]+s
此时 C C C 比 B B B 优, B B B 比 A A A 优
可以发现,无论如何, B B B 都不是最优的。所以,这种上凸的点我们是不需要的,这样就证明了:答案点一定在下凸包上。
如果是下凸包的话,又有一个性质:下凸包从左往右横坐标相邻的点对斜率递增。
诶?这不就是我们要的单调性吗!那么发现,从左往右,肯定能找到一个分界点,这个点左边的 相邻的点对 的斜率 都小于 t [ i ] + s t[i]+s t[i]+s,右边的 相邻的点对 的斜率 都大于 t [ i ] + s t[i]+s t[i]+s,那么这个分界点就是我们要的答案。
二分即可。
但是!这道例题还有一个性质: t [ i ] + s t[i]+s t[i]+s 递增。
那么我们甚至不用二分,用单调队列即可。
代码在这里。
斜率优化DP详解
本文深入探讨了斜率优化在动态规划中的应用,通过实例解析如何将O(n^2)的复杂度优化到O(nlogn)甚至O(n),关键在于发现转移方程中的单调性并利用下凸包特性进行高效求解。
462

被折叠的 条评论
为什么被折叠?



