前言
上文讲了四边形不等式在一类 DP 问题中的优化策略
可能大家会觉得,这么复杂的定理,结果只用应用在某类固定 dp 方程上,有点大炮打蚊子的感觉
本文带来了四边形不等式在另外一类非常常见的 dp 方程的应用
分治 DP
d
p
(
i
,
j
)
=
{
min
0
<
k
≤
j
{
d
p
(
i
−
1
,
k
)
+
c
(
k
,
j
)
}
,
i
>
0
0
,
i
=
0
dp(i,j) = \left\{ \begin{aligned} \min_{0<k\le j} \{dp(i-1,k) + c(k,j)\} &, i > 0 \\ 0 &, i=0 \end{aligned} \right.
dp(i,j)=⎩
⎨
⎧0<k≤jmin{dp(i−1,k)+c(k,j)}0,i>0,i=0
dp 方程说明:
朴素实现复杂度:此 dp 方程有 n ⋅ m n\cdot m n⋅m 个状态( 1 ≤ i ≤ n , 1 ≤ j ≤ m 1\le i \le n, 1\le j \le m 1≤i≤n,1≤j≤m),每个状态需要有 O ( m ) O(m) O(m) 个决策( k k k从 1 1 1遍历到 j j j),对于函数 c c c 我们就当 O ( 1 ) O(1) O(1) 的复杂度,所以整体复杂度是 O ( n ⋅ m 2 ) O(n\cdot m^2) O(n⋅m2)
特征:每一层的 dp 状态由上一层的 dp 状态推演出,而上一层的状态已经在前置逻辑中计算好
我们可以将上述方程进行一些简化,设
C
u
r
r
e
n
t
≔
d
p
(
i
)
\textcolor{Red}Current\coloneqq dp(i)
Current:=dp(i) 代表当前层状态,设
B
e
f
o
r
e
≔
d
p
(
i
−
1
)
\textcolor{Red}Before\coloneqq dp(i-1)
Before:=dp(i−1) 代表上一层已经计算好的状态,则:
C
(
i
)
=
min
0
<
j
≤
i
{
B
(
j
)
+
c
(
j
,
i
)
}
C(i) = \min_{0<j\le i} \{B(j) + c(j, i)\}
C(i)=0<j≤imin{B(j)+c(j,i)}
接下来我们看看对于这种 dp 方程,四边形不等式可以得出什么推论以帮助我们优化
推论:最佳决策点的单调性
如果函数 c c c 符合四边形不等式,那么 C ( i ) C(i) C(i) 的最佳决策点 o p t ( i ) opt(i) opt(i),必定符合 o p t ( i ) ≤ o p t ( i + 1 ) opt(i) \le opt(i+1) opt(i)≤opt(i+1)
证明
设
x
=
o
p
t
(
i
)
,
y
=
o
p
t
(
i
+
1
)
x=opt(i), y=opt(i+1)
x=opt(i),y=opt(i+1)
用反证法,假设
x
>
y
x > y
x>y
由定义可得
x
<
i
,
y
<
i
+
1
x<i, y<i+1
x<i,y<i+1
结合假设可得
y
<
x
<
i
<
i
+
1
y < x < i < i +1
y<x<i<i+1
由
x
x
x 是
C
(
i
)
C(i)
C(i) 的最佳决策点(其他的选择都比它要差),可得
B
(
x
)
+
c
(
x
,
i
)
≤
B
(
y
)
+
c
(
y
,
i
)
B(x) + c(x, i) \le B(y) + c(y, i)
B(x)+c(x,i)≤B(y)+c(y,i)
由
y
y
y 是
C
(
i
+
1
)
C(i+1)
C(i+1) 的最佳决策点,可得
B
(
y
)
+
c
(
y
,
i
+
1
)
≤
B
(
x
)
+
c
(
x
,
i
+
1
)
B(y) + c(y, i + 1) \le B(x) + c(x, i + 1)
B(y)+c(y,i+1)≤B(x)+c(x,i+1)
两式相加去除相同项,可得
c
(
x
,
i
)
+
c
(
y
,
i
+
1
)
≤
c
(
y
,
i
)
+
c
(
x
,
i
+
1
)
c(x,i)+c(y,i+1) \le c(y,i)+c(x,i+1)
c(x,i)+c(y,i+1)≤c(y,i)+c(x,i+1)
与 c 符合四边形不等式,既
c
(
y
,
i
)
+
c
(
x
,
i
+
1
)
≤
c
(
x
,
i
)
+
c
(
y
,
i
+
1
)
c(y,i) + c(x,i+1) \le c(x,i) + c(y, i+1)
c(y,i)+c(x,i+1)≤c(x,i)+c(y,i+1) 冲突
所以假设不成立
因此证明
x
≤
y
x \le y
x≤y,既
o
p
t
(
i
)
≤
o
p
t
(
i
+
1
)
opt(i)\le opt(i+1)
opt(i)≤opt(i+1)
利用定理加速 dp 决策
o
p
t
(
i
)
≤
o
p
t
(
i
+
1
)
opt(i)\le opt(i+1)
opt(i)≤opt(i+1) 也意味着
o
p
t
(
i
−
1
)
≤
o
p
t
(
i
)
opt(i-1)\le opt(i)
opt(i−1)≤opt(i)
如果我们已经知道了其中一个状态
C
(
i
)
C(i)
C(i) 的最佳决策点,那么:
- 对于所有的 C ( j ) , j < i C(j),j<i C(j),j<i,只需要在 ( 0 , m i n ( o p t ( i ) , j ) ] (0, min(opt(i), j)] (0,min(opt(i),j)] 的范围中进行决策就行了
- 对于所有的 C ( j ) , j > i C(j),j>i C(j),j>i,只需要在 [ o p t ( i ) , j ] [opt(i),j] [opt(i),j] 的范围中进行决策就行了
所以,我们可以先计算所有状态里最中间的状态 C ( m 2 ) C(\frac{m}{2}) C(2m),记录下最佳决策点 o p t ( m 2 ) opt(\frac{m}{2}) opt(2m)
决策范围是 ( 0 , m 2 ] (0,\frac{m}{2}] (0,2m],所以中共进行了 m 2 + 1 \frac{m}{2}+1 2m+1 次决策,复杂度为 O ( m ) O(m) O(m)
然后计算状态 C ( m 4 ) C(\frac{m}{4}) C(4m)和 C ( 3 ⋅ m 4 ) C(\frac{3\cdot m}{4}) C(43⋅m),
对于 C ( m 4 ) C(\frac{m}{4}) C(4m),决策范围是 ( 0 , min ( m 4 , o p t ( m 2 ) ) ] (0, \min(\frac{m}{4}, opt(\frac{m}{2}))] (0,min(4m,opt(2m))],所以有 min ( m 4 , o p t ( m 2 ) ) + 1 \min(\frac{m}{4}, opt(\frac{m}{2}))+1 min(4m,opt(2m))+1次决策
对于 C ( 3 ⋅ m 4 ) C(\frac{3\cdot m}{4}) C(43⋅m),决策范围是 [ o p t ( m 2 ) , 3 ⋅ m 4 ] [opt(\frac{m}{2}), \frac{3\cdot m}{4}] [opt(2m),43⋅m],所以有 3 ⋅ m 4 − o p t ( m 2 ) + 1 \frac{3\cdot m}{4}-opt(\frac{m}{2})+1 43⋅m−opt(2m)+1次决策
两者的决策次数为
3 ⋅ m 4 − o p t ( m 2 ) + 1 + m i n ( m 4 , o p t ( m 2 ) ) + 1 = m i n ( 3 ⋅ m 4 − o p t ( m 2 ) + m 4 , 3 ⋅ m 4 − o p t ( m 2 ) + o p t ( m 2 ) ) + 2 = m i n ( m − o p t ( m 2 ) , 3 ⋅ m 4 ) + 2 = O ( m ) \begin{aligned} &\frac{3\cdot m}{4}-opt(\frac{m}{2})+1+min(\frac{m}{4}, opt(\frac{m}{2}))+1 \\ =&min(\frac{3\cdot m}{4}-opt(\frac{m}{2})+\frac{m}{4}, \frac{3\cdot m}{4}-opt(\frac{m}{2})+opt(\frac{m}{2}))+2 \\ =&min(m-opt(\frac{m}{2}), \frac{3\cdot m}{4}) + 2 \\ =&O(m) \end{aligned} ===43⋅m−opt(2m)+1+min(4m,opt(2m))+1min(43⋅m−opt(2m)+4m,43⋅m−opt(2m)+opt(2m))+2min(m−opt(2m),43⋅m)+2O(m)
如此往复递归,直到分治收敛。根据二分特性,递归会有 O ( log m ) O(\log m) O(logm)层,每一层的复杂度都是 O ( m ) O(m) O(m),所以整体的复杂度为 O ( m ⋅ log m ) O(m \cdot \log m) O(m⋅logm)
可以用另一种更直观的方式来看复杂度
对于任意层每个节点所需要决策的范围(记为 [ d 1 , l , d 1 , r ] [d_{1,l}, d_{1,r}] [d1,l,d1,r]),决策次数的总和为
c n t = d 1 , r − d 1 , l + 1 + d 2 , r − d 2 , l + 1 ⋯ + d m , r − d m , l + 1 cnt=d_{1,r}-d_{1,l}+1 + d_{2,r}-d_{2,l}+1\cdots + d_{m,r}-d_{m,l}+1 cnt=d1,r−d1,l+1+d2,r−d2,l+1⋯+dm,r−dm,l+1
根据决策点单调性的推论,一定是互不相交的
所以可得 d 1 , l ≤ d 1 , r ≤ d 2 , l ≤ d 2 , r ≤ ⋯ ≤ d m , l ≤ d n , r d_{1,l} \le d_{1,r} \le d_{2,l} \le d{2,r} \le \cdots \le d_{m,l} \le d_{n,r} d1,l≤d1,r≤d2,l≤d2,r≤⋯≤dm,l≤dn,r,既 d i , r − d i + 1 , l ≤ 0 d_{i,r}-d_{i+1,l}\le 0 di,r−di+1,l≤0,用这个不等式多项式中两项进行消消乐,可得
c n t ≤ d m , r − d 1 , r + m = O ( m ) cnt\le d_{m,r} - d_{1,r} + m=O(m) cnt≤dm,r−d1,r+m=O(m)
用不严谨的话来说就是:每个决策点平均最多会被访问两次
代码
const int MAXM = 1000001;
int bef[MAXM], cur[MAXM];
int c(int l, int r);
void compute(int l, int r, int optl, int optr) {
if (l > r) return;
int mid = (l + r) >> 1;
cur[mid] = INFINITY;
int opt = optl;
for (int i = optl; i <= min(optr, mid); i++) {
int x = bef[i] + c(i, mid);
if (x < cur[mid]) {
cur[mid] = x;
opt = i;
}
}
compute(l, mid - 1, optl, opt);
compute(mid + 1, r, opt, optr);
}
int solve(int n, int m) {
memset(bef, 0, sizeof(bef));
for (int i = 1; i <= n; i ++) {
compute(1, m, 1, m);
memcpy(bef, cur, sizeof(cur));
}
return bef[m];
}