【学习笔记】DP 优化 1:基础优化

Page Views Count

矩阵优化 DP#

用矩阵描述每次转移时 DP 数组的线性变换,如果每次变换转移相同,可以根据矩阵乘法的结合律先快速幂计算出总的转移矩阵。

这里矩阵乘法不只是 (+,×),实际上只要 (,) 满足 有分配律, 有结合律, 有交换律即可。

证明:

((Aw×xBx×y)Cy×z)il=k=1y(j=1xAijBjk)Ckl=k=1yj=1xAijBjkCkl=j=1xk=1yAijBjkCkl=j=1xAij(k=1yBjkCkl)=(Aw×x(Bx×yCy×z))il

从上到下依次运用了左分配律、交换律、结合律以及右分配律。

比较经典的广义矩阵乘法有 (+,×),(max/min,+),(gcd,×)

其他略去不写。

数据结构优化 DP#

DP 转移区间修改时,可以考虑放到线段树上进行,类似区间加、区间 max、区间推平等操作,可以 O(nk) 优化到 O(nk1logn)

其他略去不写。

倍增优化 DP#

DP 状态由走 k 步改为走 2k 步,求解时拼起来,类似 ST 表或是树上倍增的思想。

其他略去不写。

单调队列优化 DP#

概述#

对任意状态和转移复杂度的 DP 都可以优化减少枚举状态中的一维。

要求转移方程形如:

fi=maxlij<i{fj+Ai+Bj}

其中 A 只关于 iB 只关于 j,且 li 单调不降,整理后得到:

fi=Ai+maxlij<i{fj+Bj}

发现决策点只与其自身有关,且符合滑动窗口的类型,因此可以用单调队列维护出当前决策区间的最优决策点,可以把 O(n) 枚举优化为 O(1) 转移。

例题#

Luogu-P2569 SCOI 2010 股票交易#

fi,ji 天持有 j 股的最大收益,按照题目要求容易得到:

fi,j=max1k<iW,jlmin(j+ASi,MaxP){fk,l(lj)×APi}

fi,j=max1k<iW,max(jBSi,0)lj{fk,l+(jl)×BPi}

k 的枚举可以前缀 max 优化掉,剩下对 l 的枚举区间分别是 [j,min(j+ASi,MaxP)],[max(jBSi,0),j],区间的移动具有单调性,调整枚举顺序即可。

Luogu-P3572 POI 2014 PTA-Little Bird#

写出转移方程:

fi=minj=iki1{fj+[hihj]}

看似无法把转移方程独立成只与 j 有关,但是每次最多增加 1,因此当 f 值相等时 h 值较大的更优,而其余情况 f 值更小的一定不劣,符合单调性,可以单调队列优化。

斜率优化 DP#

概述#

解决形如:

fi=maxj=0i1{fj+Ai+Bj+Ci×Dj}

其中 A,C 只关于 iB,D 只关于 j,此时由于 i,j 共同产生影响,无法独立出 j 单调队列优化。

例题:Luogu-P3195 HNOI 2008 玩具装箱

fi 为装前 i 个玩具的最小花费,设 si=j=1i(Ci+1),可以写出初步转移方程:

fi=minj=0i1{fj+(sisj1L)2}

为了方便,令 L=L+1,把平方拆开:

fi=minj=0i1{fj+si2+sj2+L22Lsi+2Lsj2sisj}

按照上面的形式分组:

fi=minj=0i1{fj+(si22Lsi)+(sj2+2Lsj)2sisj}

假设 0j1<j2<i,我们思考在怎样的条件下,从 j1 转移更优。

也就是:

fj1+(si22Lsi)+(sj12+2Lsj1)2sisj1<fj2+(si22Lsi)+(sj22+2Lsj2)2sisj2<

A 部分可以消去,再移项:

2si(sj2sj1)<(fj2+sj22+2Lsj2)(fj1+sj12+2Lsj1)

2si<(fj2+sj22+2Lsj2)(fj1+sj12+2Lsj1)sj2sj1

不等号右边类似于一个斜率 (Yj2Yj1)/(Xj2Xj1) 的形式,也就是如果拿斜率 2si 的直线判断所有的 j,那么第一个满足斜率大于 2si 的点对 (j1,j2)j1 就是最优决策点。因为显然在这之前的所有点对都是右侧点优于左侧点,而在这之后的所有点对都是左侧点优于右侧点,类似于具有凸性。

现在从线性规划的角度去思考这个问题,我们把转移方程的 min 去掉,改为:

fi=fj+(si22Lsi)+(sj2+2Lsj)2sisj

这样整理一下:

(fj+sj2+2Lsj)=2si×sj+(fisi2+2Lsi)

这符合 y=kx+b 的直线表达式,且 x,y 对应的值 sjfj+sj2+2Lsj 恰好对应上面比较 j1,j2 时的形式。

这样我们相当于是拿斜率为 2si 的直线去切决策点,截距最小的一个点即为最优决策点,此时 fisi2+2Lsi 最小,即 fi 最小。

结合上图理解,每个点表示 [0,i1] 即已经得出 DP 值的位置,容易发现拿直线去切所有决策点时,D 点的截距最小。

现在问题时如何维护这些决策点,在本题中 Xj=sj 单调递增,因此每次都会在右侧增加一个点,考虑点 (E,F,I) 三点的关系,一条任意斜率直线从下向上切 I 过程中一定会先切到 EF,也就是说 I 一定不是决策点,可以扔掉。这就形成了一个凸包。

对于取 min 的情况维护下凸包(斜率单调递增),对于取 max 的情况就要截距最大,维护上凸包(斜率单调递减)。

后面的内容均以取 min 为例子讨论。

X 与斜率 ki 均具有单调性的情况#

即当一段 (j1,j2) 斜率小于当前的斜率后就不可能再作为转移点,即判断 slope(j1,j2)ki

在右侧加入新的点 i 时不断弹出直到找到第一段 (j1,j2) 满足 slope(j1,j2)<slope(j2,i),将 i 加入。

后者的操作就是单调栈维护凸包,由于前者的操作具有单调性,使用单调队列。

每次完成前者操作后,队首即为最优决策点。

时间复杂度 O(n)

只有 X 具有单调性的情况#

维护凸包的部分同样是单调栈操作,只不过查询不具有单调性不能扔掉当前无用决策点,但每次单调栈二分即可。

时间复杂度 O(nlogn)

没有任何单调性#

李超线段树学习笔记

一些注意点#

  • 在队首弹出无用决策点或是二分决策点时,判断斜率是否取等并不重要,因为平行的直线切在任何一个点上截距都不变。

  • 在单调栈保持凸包斜率单调性时,应当保证凸包斜率严格单调,即当且仅当 slope(j1,j2)<slope(j2,i) 才停止弹栈。

  • 关于精度问题使用 long double 可以避免绝大多数问题,但是一些题目中会出现 X 不严格单调递增的情况,此时 Xj1=Xj2 是我们在计算斜率是不想看到的。一个简单的处理是:

Yj2Yj1Xj2Xj1Yj3Yj2Xj3Xj2(Yj2Yj1)(Xj3Xj2)(Yj3Yj2)(Xj2Xj1)

例题#

Luogu-P5785 SDOI 2012 任务安排#

维护结束时间是困难的,考虑拆开贡献,如果一批任务为 [l,r],用时为 s+i=lrti,那么 [l,n] 的结束时间都会增加这个值,将贡献提前计算。

sti=j=1itj,sci=j=i+1ncj,得到转移方程:

fi=minj=0i1{fj+(stistj+s)×scj}

拆开整理成:

fj(stjs)×scj=sti×(scj)+fi

这样保证 X=scj 是单调不降的,t 可能为负,斜率 sti 单调性不保证,因此单调栈维护凸包并二分。

Luogu-P6047 丝之割#

关键观察是如果两条弦相交,那么割掉 u 较小(如果 u 相等则是 v 较大)的情况下一定也割掉了另一条,这样有用的弦都是 u,v 递增。

prei,sufi 分别是 ai 的前缀 minbi 的后缀 min,转移是:

fi=minj=0i1fj+preuj+11×sufvi+1

斜率优化,可以直接使用单调队列。

参考资料#

单调队列优化 DP#

斜率优化 DP#

作者:SoyTony

出处:https://www.cnblogs.com/SoyTony/p/Learning_Notes_about_DP_Optimization_1.html

版权:本作品采用「署名-非商业性使用-相同方式共享 4.0 国际」许可协议进行许可。

posted @   SoyTony  阅读(154)  评论(1编辑  收藏  举报
相关博文:
阅读排行:
· 单线程的Redis速度为什么快?
· 展开说说关于C#中ORM框架的用法!
· Pantheons:用 TypeScript 打造主流大模型对话的一站式集成库
· SQL Server 2025 AI相关能力初探
· 为什么 退出登录 或 修改密码 无法使 token 失效
more_horiz
keyboard_arrow_up light_mode palette
选择主题
menu
点击右上角即可分享
微信分享提示