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{fi−1,k+bi−∣ai−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{fi−1,k}+bi−∣ai−j∣}
于是,我们的目标变成了求
max
k
=
1
n
f
i
−
1
,
k
\max \limits _{k=1} ^n {f_{i-1,k}}
k=1maxnfi−1,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[i−1][j−k ˙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=j−w[i],可以发现只有在 j ≡ x ( m o d w [ i ] ) j \equiv x \space (mod\space w[i]) j≡x (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[i−1][j+(y−k)w[i]]+k ˙v[i]}=k=1maxm[i]{f[i−1][j+(y−k) ˙w[i]]−(y−k)v[i]}+y ˙v[i]
令
t
=
y
−
k
t=y-k
t=y−k,则
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=y−m[i]maxy−1{f[i−1][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=0mini−1{fj+(i−(j+1)+sumi−sumj−L)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=0mini−1{fj+(i+sumi−1−L)2+(j+sumj)2−2(i+sumi−1−L)(j+sumj)}=j=0mini−1{fj+(j+sumj)2−2(i+sumi−1−L)(j+sumj)}+(i+sumi−1−L)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−(gi−L′)2=min{fj+gj 2−2(gi−L′)gj}
我们把直线的方程
y
=
k
x
+
b
y=kx+b
y=kx+b 变一下,就可以得到
b
=
y
−
k
x
b=y-kx
b=y−kx。
令
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−(gi−L′)2yj=fj+gj 2ki=2(gi−L′)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=0mini−1{yj−kixj}
k
i
k_i
ki 表示一条经过点
(
x
j
,
y
j
)
(x_j,y_j)
(xj,yj) 的直线的斜率。
把问题转化为了选择合适的 j j j,使得 b i b_i bi,也就是直线的截距最小。
- 怎么求这个点呢?
我们画一下图。
红色直线的斜率为 k i k_i ki。
我们把这条直线向上移,直到碰到一个点:
碰到的第一个点就是要求的点。
证明:反证法,若继续向上移, 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(gi−L′), 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+average2−2dis[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=0mini−1{f[j]+(s[i]−s[j])2}⟹f[i]=min{f[j]+s[i]2+s[j]2−2s[i]s[j]}⟹f[i]−s[i]2=min{f[j]+s[j]2−2s[i]s[j]}⟹b=min{y−kx}
也就是:
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 a≤b≤c≤d,都有 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 a≤b≤c,有 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 a≤b≤c≤d,有 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=0mini−1{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=0mini−1{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)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′)
也就是对于 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 会被分成若干段,使每一段中所有元素的值相同,如下图:
当我们求出了一个新的 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 pos−1,把新的三元组 ( 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)=i≤k<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)=i≤k<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)中,如果下面两个条件成立:
- w w w 满足四边形不等式;
- 对于任意的 a ≤ b ≤ c ≤ d a\leq b \leq c \leq d a≤b≤c≤d,有 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)=i≤k<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,j−1)≤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,r−1)≤k≤p(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 n≤5000
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=0mini−1{f[k][j−1]+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+j−1)/2]+sumx[i−1]⟹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]≥0⟹w(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 a≤b≤c≤d,有 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
题解
朴素算法的基础上,用树状数组 / 线段树维护最优决策。