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

『动态规划的单调性优化』

时间:2020-07-24 19:08:50      阅读:90      评论:0      收藏:0      [点我收藏+]

标签:大小   mini   递增   lock   取值   类型   乘法   double   动态   

动态规划的单调性优化

决策集合优化

\(\mathrm{dp}\)的时候决策集合只扩大不减小,直接把最大值\(/\)最小值\(/\)累加和记下来就好了.

例如:\(\mathrm{LCIS\ CH5101}\)\(f_{i,j}=\max\limits_{0\leq k<j,B_k<A_i}\{f_{i-1,k}\}+1\).

外层\(i\)不变,随着\(j\)增大,每次决策\(k\)最多增加一个,判断一下是否合法记下来即可.

单调队列优化

\(\mathrm{dp}\)的时候决策区间上下界都单调变化,可以直接记录区间和的值. 如果是最优化\(\mathrm{dp}\),那就要用滑动窗口记录区间最值.

写代码的时候,在循环开始的时候排除队首过期决策,然后取队首作为最优解,然后加入新决策. 有些边界麻烦的初值可以暴力算掉.

多重背包怎么用单调队列优化?先写方程:\(f[j]=\max\limits_{1\leq k\leq c_i}\{f[j-k\times v_i]+k\times w_i\}\).

观察:决策点每次位移\(v_i\),那就把\(j\)按照\(v_i\)的余数分类. 设\(j=u+v_i\times p\),于是:

\[f[u+v_i\times p]=\max\limits_{\max\{0,p-c_i\}\leq k\leq p-1}\{f[u+v_i\times k]+(p-k)\times w_i\} \]

这样的话可以把\(i,u\)当成定值,枚举\(p\),此时决策变量\(k\)的上下界单调变化,就可以用单调队列了.

斜率优化

多项式\(v(i,j)\)含有\(i,j\)乘积项的\(\mathrm{1D/1D}\)动态规划,一般可以用单调队列维护下凸壳\(/\)上凸壳.

\(f_i=\max\limits_{0\leq j\leq i-1}\{f_j+A(i)+B(j)+p(i)q(j)\}\),然后移项一下:

\[f_j+B(j)=-p(i)q(j)-A(i)+f_i \]

这时候把所有决策点\(j\)看成平面上的点\(P_j(-q(j),f_j+B(j))\),那么现在你要用一条斜率为\(p(i)\)的直线去切这些点,求最小截距.

一般来说,这些点都是单调递增的,所以我们可以用单调队列维护下凸壳作为最优决策集. 如果\(p(i)\)也是单调的,只要在队首操作最优决策即可,如果\(p(i)\)不单调,那就二分找最优决策点.

如果这些点不是单调递增的话,那就要用平衡树\(/\)\(\mathrm{cdq}\)分治维护凸壳. 不过用李超树求一次函数最值会更简单.

注意事项有点多:

\(1.\) 决策变量有取值范围,在推入队列的时候改为推入可取的决策变量

\(2.\) \(dp\)数组有部分初值无法用斜率优化转移得到(决策变量被取值范围限制),暴力先转移初值

\(3.\) 斜率会出现整数被\(0\)除,特判返回\(+\infty\)\(-\infty\)

\(4.\) 计算斜率可能会出锅,\(\mathrm{slope}\)函数尽量公式化:数值大的下标为\(y\),数值小的下标为\(x\),计算时用\(val(y)-val(x)\)

\(5.\) 单调队列要注意:必须在队列内有至少两个元素才能删除队首或队尾

\(6.\) 浮点数运算很容易出问题,计算斜率或比较大小时记得转为\(\mathrm{double}\)类型

\(7.\) 精度可能会出问题,适当时计算斜率的除法要转为乘法

\(8.\) 考虑单调队列内是否要存一个转移初值(如\(0\))

\(9.\) \(dp\)数组的初值:\(+\infty\)\(-\infty\)\(0\),是否要\(\mathrm{long\ long}\),无穷要开够大

\(10.\) 弹出队首不优元素和队尾不在下凸壳内元素比较斜率时,请将等号加上(\(<\)尽量写成\(\leq\)\(>\)尽量写成\(\geq\))

四边形不等式

直接记结论即可:对于整数域上的二元函数\(w(x,y)\),若其满足:

\[a\leq b\leq c\leq d,w(a,d)+w(b,c)\geq w(a,c)+w(b,d) \]

或者

\[a< b,w(a,b+1)+w(a+1,b)\geq w(a,b+1)+w(b,a+1) \]

则称\(w\)满足四边形不等式.

对于\(f_i=\min\limits_{0\leq j < i}\{f_j+w(j,i)\}\)\(w(a,b)\)满足四边形不等式,则\(f\)的决策数组\(p\)单调不减.

暴力优化的话直接从上一个决策点开始枚举即可,如果用队列维护决策点连续段可以做到\(O(n\log_2 n)\),需要用二分找分界点. 如果是二维的\(\mathrm{dp}\),每次仅从上一维转移,可以采用分治写法,时间复杂度也是每层\(O(n\log_2 n)\),如果一维\(\mathrm{dp}\)强行套\(\mathrm{cdq}\)分治的话,时间复杂度两个\(\log\).

对于\(f_{i,j}=\min\limits_{i\leq k<j}\{f_{i,k+1}+f_{k+1,j}+w(i,j)\}\),若\(f_{i,i}=w_{i,i}=0\)\(\forall a\leq b\leq c\leq d,w(a,d)\geq w(b,c)\)\(w\)满足四边形不等式,则\(f\)的决策数组\(p\)有二维决策单调性:

\[\forall i < j,p_{i,j-1}<p_{i,j}<p_{i+1,j} \]

按照长度为阶段的区间\(\mathrm{dp}\),直接在决策范围里面枚举时间复杂度就优化到\(O(n^2)\).

习题

\(\mathrm{BZOJ}4709\) 柠檬

\(\mathrm{CF868F\ Yet\ Another\ Minimization\ Problem}\)

\(\mathrm{CF321E\ Ciel\ and\ Gondolas}\)

任务安排\(4\)

『动态规划的单调性优化』

标签:大小   mini   递增   lock   取值   类型   乘法   double   动态   

原文地址:https://www.cnblogs.com/Parsnip/p/13373161.html

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