斜率优化dp的本质还是dp
只是转移耗时太大,我们需要根据其转移方程优化
两种常见的计算斜率的方法:
1.作差比较法
举个例子
当前我们的dp转移方程为:(最后求f[n]的最小值)
f[i]=f[j]+(sumt[i]+s)∗(sumc[i]−sumc[j])
我们取两个j的值,假设为k1,k2(满足k1<k2)
如果决策k1比k2优,那么一定会得到:
f[k1]+(sumt[i]+s)∗(sumc[i]−sumc[k1])<f[k2]+(sumt[i]+s)∗(sumc[i]−sumc[k2])
移项整理可得:
sumc[k1]−sumc[k2]f[k1]−f[k2]<s+sumt[i]
若将(sumc[k],f[k])看作点
左边则为两点之间的斜率
所以当斜率K满足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+sumt[i])∗sumc[j]+f[i]−sumt[i]∗sumc[i]=f[j]+s∗sumc[n]
为什么这样进行优化是正确的?
假设现在有三个决策点
emm……不想写了(好冷,手都冻僵了)
大家自己画图,然后分类讨论一下
会发现如果三个点呈上凸状,中间那个点无论在哪种情况下都不会作为最优的决策(针对求最小值的情况)