码迷,mamicode.com
首页 > 其他好文 > 详细

斜率优化

时间:2018-06-09 19:01:11      阅读:173      评论:0      收藏:0      [点我收藏+]

标签:一个   情况   col   表达   最小值   绿色   min   需要   blog   

斜率优化


1.概念

对于某些转移方程形如\(DP[i] = min / max(DP[j] + f(j))\)的DP来说,我们可以使用单调队列将其由\(O(n^{2})\)优化为\(O(n)\)。但对于一些转移方程形如\(DP[i] = min / max(DP[j] + f(i , j))\)的DP来说,因为转移中有与\(i\)有关的表达式,于是就不能贸然地使用单调队列了。这个时候我们需要将斜率优化请上台面。

我们以转移方程形如\(DP[i] = min(DP[j] + f(i, j))\)的DP为例。

尝试将DP方程化为\(DP[i] = {\color{red}{(……)}} + {\color{green}{(……)}} +{\color{orange}{(……)}}\)的形式。红色的部分为仅与\(j\)有关的表达式,绿色的部分则与\(i\)\(j\)均有关,橙色的部分只与\(i\)或常数有关。设红色部分为\(y\),绿色的部分中与\(i\)有关的部分为\(k\),与\(j\)有关的部分为\(x\),橙色的部分向左移项与\(DP[i]\)合为\(B\),这样我们就将其化成了\(B = y - kx\)的形式,整个问题就转化成了求\(B\)最小。因为在\(B\)中与\(i\)有关的部分在单次转移时相当于一个常数,所以求\(B\)最小就相当于求\(DP[i]\)最小。

对于任意\(j\),可以表示为坐标轴上一点\((x, y)\),转移时则可利用坐标计算\(y - kx\),求得\(B\)的最小值(当然算的时候别忘了计算\(B\)中的常数)。保证斜率\(k >0\),且随\(i\)单增,才可以进行下面的转移。

如何确定转移最优一点呢?这样:

技术分享图片

将斜率为\(k\)的直线上移,可发现第一个触及直线的点会使其截距最小。而又因为斜率单增,所以说此点前的所有点已经对转移没有贡献,直接弹出即可。

如果尾部在插入新的\(j\)时出现了不下凸的情况怎么办?这样:

技术分享图片

\(i\)点之上的两个点在\(i\)点插入后,将不会有对转移做出贡献的机会,因为由\(i\)点转移至当前点时所得到的截距将恒优于\(i\)点之上的两个点。所以此两点一并弹出即可。

或使用数学方法证明:记\(slope(i, j) = \dfrac{Y(i) - Y(j)}{X(i) - X(j)}\),当前点为\(l\)。若\(slope(i, j) < k (i < j)\),则说明由\(j\)转移到\(l\)较由\(i\)转移到\(l\)更优。假设\(slope(i, j) > slope(j, l)\),若\(slope(j, l) < k\),则\(l\)\(j\)更优;若\(slope(j, l)>k\),则\(slope(i, j)>k\),说明\(i\)\(j\)更优。

这样的话不论怎样,出现上凸的\(j\)点都不会是更优的转移点,所以说直接将\(j\)点删除,再\(i,l\)相连即可。

存点的结构考虑单调队列,因其可以按条件进行双向删除,单向插入,符合需求。

维护队首时,比较\(slope(head, head + 1)\)是否小于\(k\)。小于\(k\)说明此点在所求点之下,弹出。第一个\(slope(…) \geqslant k\)的点即为所求转移点。(PS:如果弹到队尾都没有符合要求的点,则至少要留下一个点转移。)

维护队尾时考虑上述证明,弹出\(slope(tail, i) < slope(tail - 1, tail)\)\(tail\)。这个就不用留点了,因为到最后还会插入一个\(i\)

成型后的有效点集大概这样,是个上凸包。

技术分享图片

大概就这样。

那么如果\(k\)\(i\)单减,转移方程求的是最小值呢?维护一个上凸包即可(维护单调队列时把小于号都反过来)。

上面所说的均是\(x\)单调且\(k\)单调的情况,那如果它们不单调呢?据说\(x\)不单调可以开平衡树或cdq分治,\(k\)不单调二分查找。然而我并不会:P

没了。

2.例题

直接看博客即可。

1.[HNOI 2008]玩具装箱

传送门

斜率优化

标签:一个   情况   col   表达   最小值   绿色   min   需要   blog   

原文地址:https://www.cnblogs.com/manziqi/p/9160365.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!