斜率优化dp的本质还是dp
只是转移耗时太大,我们需要根据其转移方程优化
两种常见的计算斜率的方法:
1.作差比较法
举个例子
当前我们的dp转移方程为:(最后求
f
[
n
]
f[n]
f[n]的最小值)
f
[
i
]
=
f
[
j
]
+
(
s
u
m
t
[
i
]
+
s
)
∗
(
s
u
m
c
[
i
]
−
s
u
m
c
[
j
]
)
f[i]=f[j]+(sumt[i]+s)*(sumc[i]-sumc[j])
f[i]=f[j]+(sumt[i]+s)∗(sumc[i]−sumc[j])
我们取两个
j
j
j的值,假设为k1,k2(满足
k
1
<
k
2
k1<k2
k1<k2)
如果决策
k
1
k1
k1比
k
2
k2
k2优,那么一定会得到:
f
[
k
1
]
+
(
s
u
m
t
[
i
]
+
s
)
∗
(
s
u
m
c
[
i
]
−
s
u
m
c
[
k
1
]
)
<
f
[
k
2
]
+
(
s
u
m
t
[
i
]
+
s
)
∗
(
s
u
m
c
[
i
]
−
s
u
m
c
[
k
2
]
)
f[k1]+(sumt[i]+s)*(sumc[i]-sumc[k1])<f[k2]+(sumt[i]+s)*(sumc[i]-sumc[k2])
f[k1]+(sumt[i]+s)∗(sumc[i]−sumc[k1])<f[k2]+(sumt[i]+s)∗(sumc[i]−sumc[k2])
移项整理可得:
f
[
k
1
]
−
f
[
k
2
]
s
u
m
c
[
k
1
]
−
s
u
m
c
[
k
2
]
<
s
+
s
u
m
t
[
i
]
\frac{f[k1]-f[k2]}{sumc[k1]-sumc[k2]}<s+sumt[i]
sumc[k1]−sumc[k2]f[k1]−f[k2]<s+sumt[i]
若将
(
s
u
m
c
[
k
]
,
f
[
k
]
)
(sumc[k],f[k])
(sumc[k],f[k])看作点
左边则为两点之间的斜率
所以当斜率K满足
K
<
s
+
s
u
m
t
[
i
]
K<s+sumt[i]
K<s+sumt[i]时,决策k1更优
知道这个后如何优化dp呢?
我们在添加决策的时候就可以根据斜率进行删减(根据题意维护一个上凸包或下凸包)
而在查找最优决策的时候
- 如果斜率满足单调性,直接单调队列e.g.例题1
- 如果不具备单调性,二分查找即可e.g[SDOI2012]任务安排
2.直接转化法
还是上面的方程
我们换个形式寻找斜率:
将dp方程表示成y=kx+b的形式
其中:
x:只与j有关,且其系数与i有关
y:只与j有关
k:只与i有关,是某个只与j有关的量的系数
b:一般是与当前要求的dp值有关的量(与i有关)
然后(x,y)只与j有关,看做平面上的点,决策可以认为是一条斜率一定的直线。
然后我们需要最大化或最小化b。
最后得到这样的式子:
(
s
+
s
u
m
t
[
i
]
)
∗
s
u
m
c
[
j
]
+
f
[
i
]
−
s
u
m
t
[
i
]
∗
s
u
m
c
[
i
]
=
f
[
j
]
+
s
∗
s
u
m
c
[
n
]
(s+sumt[i])*sumc[j]+f[i]-sumt[i]*sumc[i]=f[j]+s*sumc[n]
(s+sumt[i])∗sumc[j]+f[i]−sumt[i]∗sumc[i]=f[j]+s∗sumc[n]
为什么这样进行优化是正确的?
假设现在有三个决策点
emm……
不想写了(好冷,手都冻僵了)
大家自己画图,然后分类讨论一下
会发现如果三个点呈上凸状,中间那个点无论在哪种情况下都不会作为最优的决策(针对求最小值的情况)