斜率优化详解

斜率优化DP详解
本文深入探讨了斜率优化在动态规划中的应用,通过实例解析如何将O(n^2)的复杂度优化到O(nlogn)甚至O(n),关键在于发现转移方程中的单调性并利用下凸包特性进行高效求解。

别担心,斜率优化不是什么很毒瘤的数学知识。

例题

题目传送门

朴素做法

但这 O ( n 2 ) O(n^2) O(n2) 的做法当然不是我们追求的~

斜率优化

这个优化很强,直接把 d p dp dp 优化成 O ( n l o g n ) O(nlogn) O(nlogn) 甚至是 O ( n ) O(n) O(n) 的,所以这几乎是一个算法了。

具体是,我们需要寻找到 d p dp dp 方程中的单调性,发现单调性之后,就可以直接找到最优的那个,直接从它转移过来即可。

那么先写出这个例题的转移方程(数组的定义在朴素做法里面):
f [ i ] = min ⁡ j = 0 i − 1 { f [ j ] + t [ i ] × ( c [ i ] − c [ j ] ) + s × ( c [ n ] − c [ j ] ) } f[i]=\min\limits_{j=0}^{i-1}\{f[j]+t[i]\times (c[i]-c[j])+s\times (c[n]-c[j])\} f[i]=j=0mini1{f[j]+t[i]×(c[i]c[j])+s×(c[n]c[j])}

于是开始寻找单调性:假如从 j j j 转移到 i i i 比从 k k k 转移到 i i i 更优(且 j > k j>k j>k),那么需要满足:
f [ j ] + t [ i ] × ( c [ i ] − c [ j ] ) + s × ( c [ n ] − c [ j ] ) < f [ k ] + t [ i ] × ( c [ i ] − c [ k ] ) + s × ( c [ n ] − c [ k ] ) f[j]+t[i]\times(c[i]-c[j])+s\times(c[n]-c[j])<f[k]+t[i]\times(c[i]-c[k])+s\times(c[n]-c[k]) f[j]+t[i]×(c[i]c[j])+s×(c[n]c[j])<f[k]+t[i]×(c[i]c[k])+s×(c[n]c[k])

展开得:
f [ j ] + t [ i ] c [ i ] − t [ i ] c [ j ] + c [ n ] s − c [ j ] s < f [ k ] + t [ i ] c [ i ] − t [ i ] c [ k ] + c [ n ] s − c [ k ] s f[j]+t[i]c[i]-t[i]c[j]+c[n]s-c[j]s<f[k]+t[i]c[i]-t[i]c[k]+c[n]s-c[k]s f[j]+t[i]c[i]t[i]c[j]+c[n]sc[j]s<f[k]+t[i]c[i]t[i]c[k]+c[n]sc[k]s

搞一搞:
f [ j ] − t [ i ] c [ j ] − c [ j ] s < f [ k ] − t [ i ] c [ k ] − c [ k ] s f [ j ] − c [ j ] ( t [ i ] + s ) < f [ k ] − c [ k ] ( t [ i ] + s ) f [ j ] − f [ k ] < − ( c [ k ] − c [ j ] ) ( t [ i ] + s ) f [ j ] − f [ k ] c [ j ] − c [ k ] < t [ i ] + s f[j]-t[i]c[j]-c[j]s<f[k]-t[i]c[k]-c[k]s\\ f[j]-c[j](t[i]+s)<f[k]-c[k](t[i]+s)\\ f[j]-f[k]<-(c[k]-c[j])(t[i]+s)\\ \frac {f[j]-f[k]} {c[j]-c[k]}<t[i]+s\\ f[j]t[i]c[j]c[j]s<f[k]t[i]c[k]c[k]sf[j]c[j](t[i]+s)<f[k]c[k](t[i]+s)f[j]f[k]<(c[k]c[j])(t[i]+s)c[j]c[k]f[j]f[k]<t[i]+s

诶?左边很像一个斜率耶。

假如有两个点坐标为 ( c [ j ] , f [ j ] ) , ( c [ k ] , f [ k ] ) (c[j],f[j]),(c[k],f[k]) (c[j],f[j]),(c[k],f[k]),那么左边这个东西就是经过这两点的直线的斜率。

也就是说,假如两个点 j , k j,k j,k 的斜率小于 t [ i ] + s t[i]+s t[i]+s,那么用 j j j 来更新 i i i 比用 k k k 来更新 i i i 更优。

把前面的 i − 1 i-1 i1 个坐标( c [ j ] , f [ j ] c[j],f[j] c[j],f[j])画出来之后,发现只有这些点形成的下凸包上的点是有用的。

为什么呢?

显然,在最下面、最左边、最右边的点一定在下凸包上,假如我们选一个不在下凸包上的点,那么一定存在另外两个在下凸包上点,与它的位置关系满足下面三个中的一个(设该点为 B B B,另外两个在下凸包上的点为 A A A C C C):
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
这三种情况有一个共同的特点,也就是 A B AB AB 的斜率大于 B C BC BC 的斜率。

也就是: f [ B ] − f [ A ] c [ B ] − c [ A ] > f [ C ] − f [ B ] c [ C ] − c [ B ] \frac {f[B]-f[A]} {c[B]-c[A]} > \frac {f[C]-f[B]} {c[C]-c[B]} c[B]c[A]f[B]f[A]>c[C]c[B]f[C]f[B]   → \to   f [ C ] − f [ B ] c [ C ] − c [ B ] < f [ B ] − f [ A ] c [ B ] − c [ A ] \frac {f[C]-f[B]} {c[C]-c[B]} < \frac {f[B]-f[A]} {c[B]-c[A]} c[C]c[B]f[C]f[B]<c[B]c[A]f[B]f[A]

那么 t [ i ] + s t[i]+s t[i]+s 与他们的关系有三种:

  1. t [ i ] + s < f [ C ] − f [ B ] c [ C ] − c [ B ] < f [ B ] − f [ A ] c [ B ] − c [ A ] t[i]+s < \frac {f[C]-f[B]} {c[C]-c[B]} < \frac {f[B]-f[A]} {c[B]-c[A]} t[i]+s<c[C]c[B]f[C]f[B]<c[B]c[A]f[B]f[A]
    此时 B B B C C C 优, A A A B B B
  2. f [ C ] − f [ B ] c [ C ] − c [ B ] < t [ i ] + s < f [ B ] − f [ A ] c [ B ] − c [ A ] \frac {f[C]-f[B]} {c[C]-c[B]} < t[i]+s < \frac {f[B]-f[A]} {c[B]-c[A]} c[C]c[B]f[C]f[B]<t[i]+s<c[B]c[A]f[B]f[A]
    此时 C C C B B B 优, A A A B B B
  3. f [ C ] − f [ B ] c [ C ] − c [ B ] < f [ B ] − f [ A ] c [ B ] − c [ A ] < t [ i ] + s \frac {f[C]-f[B]} {c[C]-c[B]} < \frac {f[B]-f[A]} {c[B]-c[A]} < t[i]+s c[C]c[B]f[C]f[B]<c[B]c[A]f[B]f[A]<t[i]+s
    此时 C C C B B B 优, B B B A A A

可以发现,无论如何, B B B 都不是最优的。所以,这种上凸的点我们是不需要的,这样就证明了:答案点一定在下凸包上

如果是下凸包的话,又有一个性质:下凸包从左往右横坐标相邻的点对斜率递增。

诶?这不就是我们要的单调性吗!那么发现,从左往右,肯定能找到一个分界点,这个点左边的 相邻的点对 的斜率 都小于 t [ i ] + s t[i]+s t[i]+s,右边的 相邻的点对 的斜率 都大于 t [ i ] + s t[i]+s t[i]+s,那么这个分界点就是我们要的答案。

二分即可。

但是!这道例题还有一个性质: t [ i ] + s t[i]+s t[i]+s 递增。

那么我们甚至不用二分,用单调队列即可。

代码在这里

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值