动态规划优化 课件

本文详细介绍了动态规划的优化技巧,包括单调队列优化、斜率优化和四边形不等式优化,以及如何应用于多重背包、股票交易、玩具装箱等问题。通过这些方法,可以将复杂问题的时间复杂度降低到线性或准线性,提高算法效率。此外,还讨论了数据结构如单调队列和线段树在动态规划中的应用,以减少枚举操作,实现高效求解。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

upd on 20220405 修了炸了的图和 LaTeX

动态规划优化

RabbieWjy

题单:https://www.luogu.com.cn/training/144843


有的时候,普通的动态规划不能通过题目,需要用到一些数据结构或思想进行优化。

单调队列优化

前置知识

  • 单调队列

主要思想

在 dp 转移的时候,会取上一个阶段最优的答案进行转移得到现在的答案。

而一个一个枚举上一个阶段的所有情况会导致时间复杂度增加,所以我们可以使用单调队列进行优化。

由于单调队列的时间复杂度很小,所以经常被使用。

例题

CF372C Watching Fireworks is Fun https://codeforces.com/problemset/problem/372/C

解法

普通的 dp 解法时间复杂度为 O ( m n 2 ) O(mn^2) O(mn2),显然过不去。

观察转移方程: f i , j f_{i,j} fi,j​ 表示第 i i i​ 个烟花,在位置 j j j​ 的最优答案。
f i , j = max ⁡ k = 1 n { f i − 1 , k + b i − ∣ a i − j ∣ } f_{i,j} = \max \limits _{k=1} ^{n} \{f_{i-1,k}+b_i-|a_i-j|\} fi,j=k=1maxn{fi1,k+biaij}

由于我们枚举了 i i i j j j,所以可以把确定的量提出来:
f i , j = max ⁡ k = 1 n { f i − 1 , k } + b i − ∣ a i − j ∣ } f_{i,j} = \max \limits _{k=1} ^n \{f_{i-1,k}\}+b_i-|a_i-j|\} fi,j=k=1maxn{fi1,k}+biaij}
于是,我们的目标变成了求
max ⁡ k = 1 n f i − 1 , k \max \limits _{k=1} ^n {f_{i-1,k}} k=1maxnfi1,k
可以用单调队列维护这个值,查询的时间复杂度均摊 O ( 1 ) O(1) O(1)

时间复杂度降为了 O ( m n ) O(mn) O(mn),可以过。

单调队列优化多重背包

观察一下朴素多重背包算法的式子:
f [ i ] [ j ] = max ⁡ k = 0 m [ i ] { f [ i − 1 ] [ j − k   ˙ w [ i ] ] + k   ˙ v [ i ] } f[i][j]=\max \limits _{k=0} ^{m[i]} \{ f[i-1][j-k\dot \space w[i]]+k\dot \space v[i] \} f[i][j]=k=0maxm[i]{f[i1][jk ˙w[i]]+k ˙v[i]}
其中 i i i 表示现在枚举到第 i i i 中物品, j j j 表示已经用了的背包容量, k k k 表示第 i i i 种物品放几个, w [ i ] w[i] w[i] 表示体积, v [ i ] v[i] v[i]​ 表示价值, m [ i ] m[i] m[i] 表示物品个数。

x = j − w [ i ] x=j-w[i] x=jw[i],可以发现只有在 j ≡ x   ( m o d   w [ i ] ) j \equiv x \space (mod\space w[i]) jx (mod w[i])​ 的情况下才能转移。

我们把这个式子改一下:
f [ i ] [ j + y   ˙ w [ i ] ] = max ⁡ k = 1 m [ i ] { f [ i − 1 ] [ j + ( y − k ) w [ i ] ] + k   ˙ v [ i ] } = max ⁡ k = 1 m [ i ] { f [ i − 1 ] [ j + ( y − k )   ˙ w [ i ] ] − ( y − k ) v [ i ] } + y   ˙ v [ i ] \begin{aligned} f[i][j+y\dot \space w[i]] &=\max \limits _{k=1} ^{m[i]} \{ f[i-1][j+(y-k)w[i]]+k\dot \space v[i] \}\\ &= \max \limits _{k=1} ^{m[i]} \{ f[i-1][j+(y-k) \dot \space w[i]] -(y-k)v[i] \}+y\dot \space v[i] \end{aligned} f[i][j+y ˙w[i]]=k=1maxm[i]{f[i1][j+(yk)w[i]]+k ˙v[i]}=k=1maxm[i]{f[i1][j+(yk) ˙w[i]](yk)v[i]}+y ˙v[i]
t = y − k t=y-k t=yk​​,则
f [ i ] [ j + y   ˙ w [ i ] ] = max ⁡ t = y − m [ i ] y − 1 { f [ i − 1 ] [ j + t   ˙ w [ i ] ] − t   ˙ v [ i ] } + y   ˙ v [ i ] f[i][j+y\dot \ w[i]]=\max \limits _{t=y-m[i]} ^{y-1} \{ f[i-1][j+t\dot \ w[i]] - t\dot \ v[i] \}+y\dot \ v[i] f[i][j+y ˙w[i]]=t=ym[i]maxy1{f[i1][j+t ˙w[i]]t ˙v[i]}+y ˙v[i]
花括号内的东西可以用单调队列维护。

枚举 j j j​ 的时间复杂度为 O ( w [ i ] ) O(w[i]) O(w[i])​,枚举 t t t​ 的时间复杂度为 O ( [ W w [ i ] ] ) O([\tfrac {W}{w[i]}]) O([w[i]W])​,

总的时间复杂度就是 O ( n ) × O ( w [ i ] ) × O ( [ W w [ i ] ] ) = O ( n W ) O(n)\times O(w[i]) \times O([\tfrac{W}{w[i]}])=O(nW) O(n)×O(w[i])×O([w[i]W])=O(nW)​。

练习题

多重背包板子:Luogu P1776 宝物筛选 https://www.luogu.com.cn/problem/P1776(用单调队列做)

Loj #10183 股票交易 https://loj.ac/p/10183

斜率优化

主要思想

有一些题目,可以把转移方程看做直线的方程,把问题转化为求二维平面上选择一些点,最小化直线的截距。

例题

Loj 玩具装箱 https://loj.ac/p/10188

解法

状态转移方程: f i f_i fi​​​ 表示以 i i i​ 为右端点分一段的最小代价, s u m i sum_i sumi​ 表示 c c c​​ 数组的前缀和。
f i = min ⁡ j = 0 i − 1 { f j + ( i − ( j + 1 ) + s u m i − s u m j − L ) 2 } f_{i}=\min \limits _{j=0} ^{i-1} \{ f_j + (i-(j+1) + sum_i-sum_j - L) ^2 \} fi=j=0mini1{fj+(i(j+1)+sumisumjL)2}
枚举 i i i,把确定的提出来:
f i = min ⁡ j = 0 i − 1 { f j + ( i + s u m i − 1 − L ) 2 + ( j + s u m j ) 2 − 2 ( i + s u m i − 1 − L ) ( j + s u m j ) } = min ⁡ j = 0 i − 1 { f j + ( j + s u m j ) 2 − 2 ( i + s u m i − 1 − L ) ( j + s u m j ) } + ( i + s u m i − 1 − L ) 2 \begin{aligned} f_i &= \min \limits _{j=0} ^{i-1} \{ f_j + (i+sum_i - 1-L) ^2 + (j + sum_j) ^2 - 2 (i+sum_i-1-L)(j+sum_j) \}\\ &= \min \limits _{j=0} ^{i-1} \{ f_j+(j+sum_j) ^2 - 2(i + sum_i-1-L)(j + sum_j) \} + (i+sum_i - 1 - L) ^2 \end{aligned} fi=j=0mini1{fj+(i+sumi1L)2+(j+sumj)22(i+sumi1L)(j+sumj)}=j=0mini1{fj+(j+sumj)22(i+sumi1L)(j+sumj)}+(i+sumi1L)2
g i = s u m i + i g_i=sum_i+i gi=sumi+i L ′ = L + 1 L'=L+1 L=L+1,则
f i − ( g i − L ′ ) 2 = min ⁡ { f j + g j   2 − 2 ( g i − L ′ ) g j } f_i-(g_i-L')^2 = \min \{ f_j+g_j\ ^2 - 2(g_i-L')g_j \} fi(giL)2=min{fj+gj 22(giL)gj}
我们把直线的方程 y = k x + b y=kx+b y=kx+b​ 变一下,就可以得到 b = y − k x b=y-kx b=ykx​。


b i = f i − ( g i − L ′ ) 2 y j = f j + g j   2 k i = 2 ( g i − L ′ ) x j = g j b_i=f_i-(g_i-L') ^2\\ y_j = f_j+g_j\ ^2\\ k_i = 2(g_i-L')\\ x_j = g_j bi=fi(giL)2yj=fj+gj 2ki=2(giL)xj=gj
我们就成功地把转移方程变成了直线方程:
b i = min ⁡ j = 0 i − 1 { y j − k i x j } b_i=\min \limits _{j=0} ^{i-1} \{ y_j - k_i x_j \} bi=j=0mini1{yjkixj}
k i k_i ki 表示一条经过点 ( x j , y j ) (x_j,y_j) (xj,yj)​ 的直线的斜率。

把问题转化为了选择合适的 j j j,使得 b i b_i bi,也就是直线的截距最小。

  • 怎么求这个点呢?

我们画一下图。qOAi8I.png

红色直线的斜率为 k i k_i ki

我们把这条直线向上移,直到碰到一个点:

qOAl2q.png
碰到的第一个点就是要求的点。

证明:反证法,若继续向上移, b i b_i bi 会继续变大,所以后面的都不会比这个点更优。

不难发现可能的答案在下凸壳(黑色线)上。

所以我们不需要枚举每一个点,只需要维护下凸壳上的点即可。

这个点的性质为:它和左边的点连成的直线的斜率 ≤ k i < \leq k_i< ki< 它和右边的点连成的直线的斜率。

而本题中, k i = 2 ( g i − L ′ ) k_i=2(g_i-L') ki=2(giL)​​​, g i g_i gi​​​ 随着 i i i​​​ 的增加而增加,所以 k i k_i ki​​​​ 是递增的。

所以可以用单调队列维护下凸壳,用一个指针 a n s ans ans 维护答案。

由于 k i k_i ki 单调递增,所以每次 a n s ans ans​ 的移动次数为均摊 O ( 1 ) O(1) O(1)

在更新完 f i f_i fi 后,我们把 ( x i , y i ) (x_i,y_i) (xi,yi)​ 也加进去。

这样,就成功地把时间复杂度降到了 O ( n ) O(n) O(n)

总结

斜率优化的思想就是:把状态转移方程通过转化,把确定的量提到外面来,变成直线方程,使点的坐标代表待定的值,斜率和截距代表确定的值和待求的值,再转化成让截距最小的问题。

练习题

[SDOI2016] 征途

https://loj.ac/p/2035 / https://www.luogu.com.cn/problem/P4072

题解
a n s = m 2 ∑ ( d i s [ i ] − a v e r a g e ) 2 m = m ∑ ( d i s [ i ] − a v e r a g e ) 2 = m ∑ ( d i s [ i ] 2 + a v e r a g e 2 − 2 d i s [ i ]   ˙ a v e r a g e ) = m ∑ ( d i s [ i ] 2 ) − 2   ˙ s u m d i s 2 + m 2   ˙ s u m d i s 2 m 2 = m ∑ ( d i s [ i ] 2 ) − s u m d i s 2 \begin {aligned} ans &= m ^2 \frac {\sum (dis[i]-average)^2}{m}\\ &= m\sum(dis[i]-average)^2\\ &= m\sum(dis[i] ^2 + average ^2 - 2dis[i]\dot \ average)\\ &= m\sum(dis[i]^2)-2\dot \ sumdis ^2 + m^2 \dot \ \frac {sumdis^2}{m^2}\\ &= m\sum(dis[i] ^2) - sumdis^2 \end {aligned} ans=m2m(dis[i]average)2=m(dis[i]average)2=m(dis[i]2+average22dis[i] ˙average)=m(dis[i]2)2 ˙sumdis2+m2 ˙m2sumdis2=m(dis[i]2)sumdis2
所以问题变为了使 ∑ ( d i s [ i ] 2 ) \sum (dis[i]^2) (dis[i]2) 最小。

状态转移:
f [ i ] = min ⁡ j = 0 i − 1 { f [ j ] + ( s [ i ] − s [ j ] ) 2 }    ⟹    f [ i ] = min ⁡ { f [ j ] + s [ i ] 2 + s [ j ] 2 − 2 s [ i ] s [ j ] }    ⟹    f [ i ] − s [ i ] 2 = min ⁡ { f [ j ] + s [ j ] 2 − 2 s [ i ] s [ j ] }    ⟹    b = min ⁡ { y − k x } f[i]=\min \limits _{j=0} ^{i-1} \{ f[j]+(s[i]-s[j])^2 \}\\ \implies f[i] = \min \{ f[j]+s[i] ^2 + s[j] ^2 - 2 s[i]s[j] \}\\ \implies f[i]-s[i] ^2 = \min \{ f[j]+s[j] ^2 - 2s[i]s[j] \}\\ \implies b = \min \{ y-kx \} f[i]=j=0mini1{f[j]+(s[i]s[j])2}f[i]=min{f[j]+s[i]2+s[j]22s[i]s[j]}f[i]s[i]2=min{f[j]+s[j]22s[i]s[j]}b=min{ykx}
也就是:
b [ i ] = f [ i ] − s [ i ] 2 y [ j ] = f [ j ] + s [ j ] 2 k [ i ] = 2 s [ i ] x [ j ] = s [ j ] b[i]=f[i]-s[i] ^2\\ y[j]=f[j]+s[j] ^2\\ k[i]=2s[i]\\ x[j]=s[j] b[i]=f[i]s[i]2y[j]=f[j]+s[j]2k[i]=2s[i]x[j]=s[j]
后面就和上面那道题一样了。

四边形不等式优化

四边形不等式

w ( x , y ) w(x,y) w(x,y)是定义在整数集合上的二元函数。若对于定义域上的任意整数 a , b , c , d a,b,c,d a,b,c,d​,其中 a ≤ b ≤ c ≤ d a\leq b \leq c \leq d abcd​,都有 w ( a , d ) + w ( b , c ) ≥ w ( a , c ) + w ( b , d ) w(a,d)+w(b,c) \geq w(a,c) + w(b,d) w(a,d)+w(b,c)w(a,c)+w(b,d)​ 成立,则称函数 w w w​​ 满足四边形不等式

若等号永远成立,则称函数 满足四边形恒等式

定理(另一种定义)

w ( x , y ) w(x,y) w(x,y)​​ 是定义在整数集合上的二元函数。若对于定义域上的任意整数 a , b a,b a,b​,其中 a < b a <b a<b​,

都有 w ( a , b + 1 ) + w ( a + 1 , b ) ≥ w ( a , b ) + w ( a + 1 , b + 1 ) w(a,b + 1) + w(a+1,b) \geq w(a,b)+w(a+1,b+1) w(a,b+1)+w(a+1,b)w(a,b)+w(a+1,b+1)​ 成立,则函数 w w w​ 满足四边形不等式。

定理证明

对于 a < c a<c a<c,有 w ( a , c + 1 ) + w ( a + 1 , c ) ≥ w ( a , c ) + w ( a + 1 , c + 1 ) w(a,c+1)+w(a+1,c) \geq w(a,c)+w(a+1,c+1) w(a,c+1)+w(a+1,c)w(a,c)+w(a+1,c+1)

对于 a + 1 < c a+1 <c a+1<c,有 w ( a + 1 , c + 1 ) + w ( a + 2 , c ) ≥ w ( a + 1 , c ) + w ( a + 1 , c + 1 ) w(a+1,c+1)+w(a+2,c) \geq w(a+1,c)+w(a+1,c+1) w(a+1,c+1)+w(a+2,c)w(a+1,c)+w(a+1,c+1)

两式相加,得到 w ( a , c + 1 ) + w ( a + 2 , c ) ≥ w ( a + 1 , c ) + w ( a + 2 , c + 1 ) w(a,c+1)+w(a+2,c) \geq w(a+1,c)+w(a+2,c+1) w(a,c+1)+w(a+2,c)w(a+1,c)+w(a+2,c+1)

以此类推,对任意的 a ≤ b ≤ c a \leq b \leq c abc,有 w ( a , c + 1 ) + w ( b , c ) ≥ w ( a , c ) + w ( b , c + 1 ) w(a,c+1)+w(b,c) \geq w(a,c)+w(b,c+1) w(a,c+1)+w(b,c)w(a,c)+w(b,c+1)

同理,对任意的 a ≤ b ≤ c ≤ d a\leq b \leq c \leq d abcd,有 w ( a , d ) + w ( b , c ) ≥ w ( a , c ) + w ( b , d ) w(a,d)+w(b,c) \geq w(a,c)+w(b,d) w(a,d)+w(b,c)w(a,c)+w(b,d)

一维线性 dp 的四边形不等式优化

决策单调性

对于形如 f [ i ] = min ⁡ j = 0 i − 1 { f [ j ] + v a l ( j , i ) } f[i]=\min \limits _{j=0} ^{i-1} \{ f[j] + val(j,i) \} f[i]=j=0mini1{f[j]+val(j,i)} 的转移方程,记 p [ i ] p[i] p[i] 为令 f [ i ] f[i] f[i] 取到最小值的值,即 f [ i ] f[i] f[i] 的最优决策。若 p p p 单调不减,则称 f f f​ 具有决策单调性。

定理

在状态转移方程 f [ i ] = min ⁡ j = 0 i − 1 { f [ j ] + v a l ( j , i ) } f[i]=\min \limits _{j=0} ^{i-1} \{ f[j] + val(j,i) \} f[i]=j=0mini1{f[j]+val(j,i)} 中,若函数 v a l val val 满足四边形不等式,则 f f f​ 具有决策单调性。

定理证明

f [ i ] = min ⁡ f [ j ] + w ( j , i )    ⟹    f [ p [ i ] ] + w ( p [ i ] , i ) ≤ f [ j ] + w ( j , i )       ( 1 ) j ≤ p [ i ] ≤ i ≤ i ′    ⟹    w ( j , i ′ ) + w ( p [ i ] , i ) ≥ w ( j , i ) + w ( p [ i ] , i ′ )    ⟹    w ( j , i ′ ) − w ( j , i ) ≥ w ( p [ i ] , i ′ ) − w ( p [ i ] , i )       ( 2 ) ( 1 ) + ( 2 )    ⟹    f [ j ] + w ( j , i ′ ) ≥ f [ p [ i ] ] + w ( p [ i ] , i ′ ) f[i]=\min {f[j]+w(j,i)}\\ \implies f[p[i]]+w(p[i],i) \leq f[j]+w(j,i) \space\space\space\space\space (1)\\ j\leq p[i] \leq i \leq i' \\ \implies w(j,i')+w(p[i],i)\geq w(j,i)+w(p[i],i')\\ \implies w(j,i')-w(j,i) \geq w(p[i],i') - w(p[i],i)\space\space\space\space\space (2)\\ (1)+(2) \implies f[j]+w(j,i') \geq f[p[i]]+w(p[i],i') f[i]=minf[j]+w(j,i)f[p[i]]+w(p[i],i)f[j]+w(j,i)     (1)jp[i]iiw(j,i)+w(p[i],i)w(j,i)+w(p[i],i)w(j,i)w(j,i)w(p[i],i)w(p[i],i)     (2)(1)+(2)f[j]+w(j,i)f[p[i]]+w(p[i],i)

也就是对于 i ′ i' i 来说, p [ i ] p[i] p[i] j j j 更优,即 p [ i ′ ] ≥ p [ i ] p[i'] \geq p[i] p[i]p[i]

优化过程

f f f 具有决策单调性时, p p p 会被分成若干段,使每一段中所有元素的值相同,如下图:

qOkLgx.png

当我们求出了一个新的 f [ i ] f[i] f[i],就可以通过一些操作计算出有哪些 i ′ i' i 的最优决策是 p [ i ] p[i] p[i]

根据决策单调性,我们一定可以找出一个位置 p o s pos pos,使得 p o s pos pos 之前的所有位置目前存储的决策比 p [ i ] p[i] p[i] 更优,而 p o s pos pos 及以后的所有位置目前存储的决策不比 p [ i ] p[i] p[i]​ 更优。

我们的目标就变为了找出 p o s pos pos,并把 p o s pos pos 及以后的所有位置存储的决策更新为 p [ i ] p[i] p[i]

直接暴力修改显然会超时,还不如不优化。这时,我们可以借助队列。

我们把 p p p​​​​ 的每一段用一个三元组记录下来: ( p t , l t , r t ) (p_t,l_t,r_t) (pt,lt,rt)​​​​​,其中 p p p​​​ 记录的是当前存储的决策, l l l​​​ 和 r r r​​​ 分别时这一段的左端点和右端点。设队尾为 ( p 0 , l 0 , r 0 ) (p_0,l_0,r_0) (p0,l0,r0)​​​。

如果对于 l 0 l_0 l0​ 来说, p [ i ] p[i] p[i]​ 比 p 0 p_0 p0​​​ 更优,则代表我们需要更新这一段存储的决策,直接弹出队尾;

如果对于 r 0 r_0 r0​​​ 来说, p 0 p_0 p0​​​ 比 p [ i ] p[i] p[i]​​​ 更优,则代表我们已经找到了最右的存储决策比 p [ i ] p[i] p[i] 更优的点,即 p o s − 1 pos-1 pos1​,把新的三元组 ( p [ i ] , r 0 + 1 , n ) (p[i],r_0+1,n) (p[i],r0+1,n)​​ 插入队尾;

否则,进行二分查找,找到 p o s pos pos,更新 r 0 r_0 r0,把新三元组 ( p [ i ] , p o s , n ) (p[i],pos,n) (p[i],pos,n)​ 插入队尾。

这样,我们就把 O ( n 2 ) O(n^2) O(n2) 的时间复杂度优化到了 O ( n log ⁡ n ) O(n \log n) O(nlogn)​。

二维区间dp的四边形不等式优化

朴素的转移方程: f ( i , j ) = min ⁡ i ≤ k < j { f ( i , k ) + f ( k + 1 , j ) + w ( i , j ) } f(i,j)=\min \limits _{i \leq k < j} \{ f(i,k)+f(k+1,j)+w(i,j) \} f(i,j)=ik<jmin{f(i,k)+f(k+1,j)+w(i,j)}

定理1

在转移方程 f ( i , j ) = min ⁡ i ≤ k < j { f ( i , k ) + f ( k + 1 , j ) + w ( i , j ) } f(i,j)=\min \limits _{i \leq k < j} \{ f(i,k)+f(k+1,j)+w(i,j) \} f(i,j)=ik<jmin{f(i,k)+f(k+1,j)+w(i,j)} f ( i , i ) = w ( i , i ) = 0 f(i,i)=w(i,i)=0 f(i,i)=w(i,i)=0)中,如果下面两个条件成立:

  1. w w w 满足四边形不等式;
  2. 对于任意的 a ≤ b ≤ c ≤ d a\leq b \leq c \leq d abcd,有 w ( a , d ) ≥ w ( b , c ) w(a,d) \geq w(b,c) w(a,d)w(b,c)​。

那么 f f f 也满足四边形不等式。

定理2(二维决策单调性)

在转移方程 f ( i , j ) = min ⁡ i ≤ k < j { f ( i , k ) + f ( k + 1 , j ) + w ( i , j ) } f(i,j)=\min \limits _{i \leq k < j} \{ f(i,k)+f(k+1,j)+w(i,j) \} f(i,j)=ik<jmin{f(i,k)+f(k+1,j)+w(i,j)} f ( i , i ) = w ( i , i ) = 0 f(i,i)=w(i,i)=0 f(i,i)=w(i,i)=0)中,记 p ( i , j ) p(i,j) p(i,j) f ( i , j ) f(i,j) f(i,j) 的最优决策。

如果 f f f 满足四边形不等式,那么对于任意 i < j i<j i<j,有 p ( i , j − 1 ) ≤ p ( i , j ) ≤ p ( i + 1 , j ) p(i,j-1) \leq p(i,j) \leq p(i+1,j) p(i,j1)p(i,j)p(i+1,j)


有了定理2,我们就只需要在 p ( l , r − 1 ) ≤ k ≤ p ( l + 1 , r ) p(l,r-1) \leq k \leq p(l+1,r) p(l,r1)kp(l+1,r) 的范围内枚举 k k k,时间复杂度为 O ( n 2 ) O(n^2) O(n2)

练习题

Luogu P1880 石子合并

https://www.luogu.com.cn/problem/P1880 n ≤ 5000 n\leq 5000 n5000

Luogu P4767 [IOI2000] 邮局

https://www.luogu.com.cn/problem/P4767

题解

转移方程:
f [ i ] [ j ] = min ⁡ k = 0 i − 1 { f [ k ] [ j − 1 ] + w ( k + 1 , i ) } f[i][j]=\min \limits _{k=0} ^{i-1} \{ f[k][j-1]+w(k+1,i) \} f[i][j]=k=0mini1{f[k][j1]+w(k+1,i)}
其中 f [ i ] [ j ] f[i][j] f[i][j] 表示前 i i i 个村庄放了 j j j 个邮局的最小距离和, w ( i , j ) w(i,j) w(i,j) 表示第 i i i ~ j j j 个村庄中放一个邮局的最小距离和。

显然在一个区间中,邮局要放在最中间的那个村庄那里。

s u m x [ i ] sumx[i] sumx[i] 表示前 i i i 个村庄的坐标和。

对于 w w w
w ( i , j ) = s u m x [ j ] − s u m x [ ( i + j ) / 2 ] − s u m x [ ( i + j − 1 ) / 2 ] + s u m x [ i − 1 ]    ⟹    w ( l , r + 1 ) + w ( l + 1 , r ) − w ( l , r ) − w ( l + 1 , r + 1 ) = s u m x [ ( l + r + 1 ) / 2 ] − s u m x [ ( l + r − 1 ) / 2 ] ≥ 0    ⟹    w ( l , r + 1 ) + w ( l + 1 , r ) ≥ w ( l , r ) + w ( l + 1 , r + 1 ) w(i,j)=sumx[j]-sumx[(i+j)/2]-sumx[(i+j-1)/2] + sumx[i-1]\\ \implies w(l,r+1)+w(l+1,r)-w(l,r) - w(l+1,r+1)=sumx[(l+r+1)/2]-sumx[(l+r-1)/2]\geq 0\\ \implies w(l,r+1)+w(l+1,r) \geq w(l,r)+w(l+1,r+1) w(i,j)=sumx[j]sumx[(i+j)/2]sumx[(i+j1)/2]+sumx[i1]w(l,r+1)+w(l+1,r)w(l,r)w(l+1,r+1)=sumx[(l+r+1)/2]sumx[(l+r1)/2]0w(l,r+1)+w(l+1,r)w(l,r)+w(l+1,r+1)
所以 w w w​ 满足四边形不等式。

又因为显然对于任意的 a ≤ b ≤ c ≤ d a\leq b \leq c \leq d abcd,有 w ( a , d ) ≥ w ( b , c ) w(a,d) \geq w(b,c) w(a,d)w(b,c)

所以 f f f 满足四边形不等式,具有二维决策单调性。

时间复杂度为 O ( n V ) O(nV) O(nV)

SPOJ LARMY

https://www.spoj.com/problems/LARMY/

KMP(?)

主要是思想。

KMP算法中,通过记录失配指针减少枚举的量,优化了时间复杂度。AC自动机就运用了这种思路。

扩展KMP算法中,通过记录最靠右的已经算出的区间,让待计算的一部分直接使用之前算出的结果,减少了枚举的量,优化了时间复杂度。Manacher也运用了类似的思路。

数据结构优化

在一些情况下,我们可以用数据结构维护决策的候选集合,从而快速执行插入、查找、删除等操作。

主要是把转移的一部分过程用数据结构优化。

练习题

(注意选用好写、适用的数据结构)

Luogu P1442 铁球落地

https://www.luogu.com.cn/problem/P1442

题解

线段树优化dp。
先离散化,预处理出每一块木板左边会掉到那块木板,右边会掉到哪里,再从下往上dp。
预处理的时候用线段树优化。

Luogu P1020 导弹拦截

https://www.luogu.com.cn/problem/P1020

题解

朴素算法的基础上,用树状数组 / 线段树维护最优决策。

其他的dp题

CF1627E Not Escaping

https://codeforces.com/problemset/problem/1627/E

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值