[IOI2000] 邮局 加强版 题解
考虑动态规划,设 f i , j f_{i,j} fi,j 为经过了 i i i 个村庄,正在建第 j j j 个邮局的最优距离。
以及 w i , j w_{i,j} wi,j 表示区间 [ i , j ] [i,j] [i,j] 内建一个邮局时的距离总和。
a a a 数组表示每个村庄的坐标编号。
朴素版状态转移方程:
f
i
,
j
=
min
(
f
i
,
j
,
f
k
,
j
−
1
+
w
k
+
1
,
i
)
k
∈
[
0
,
i
)
f_{i,j}=\min(f_{i,j},f_{k,j-1}+w_{k+1,i}) \\ k\in [0,i)
fi,j=min(fi,j,fk,j−1+wk+1,i)k∈[0,i)
根据初一上册数学,可知在区间
[
x
,
y
]
[x,y]
[x,y] 中距离所有点的距离之和最短的点为:
若 2 ∣ x + y 2\mid x+y 2∣x+y,则点位于 ⌊ x + y 2 ⌋ \lfloor\frac{x+y}{2}\rfloor ⌊2x+y⌋。
反之位于 ⌊ x + y + 1 2 ⌋ \lfloor\frac{x+y+1}{2}\rfloor ⌊2x+y+1⌋。
注意到,上述状态转移方程,有三个未知数: i , j , k i,j,k i,j,k。可得时间复杂度为 O ( P V 3 ) O(PV^3) O(PV3),肯定过不了。
考虑四边形不等式优化。
注意到,
w
w
w 函数的状态转移方程为:
w
l
,
r
+
1
=
w
l
,
r
+
a
r
+
1
−
a
⌊
l
+
r
+
1
2
⌋
w_{l,r+1}=w_{l,r}+a_{r+1}-a_{\lfloor\frac{l+r+1}{2}\rfloor}
wl,r+1=wl,r+ar+1−a⌊2l+r+1⌋
需要简化,过程如下,虽复杂,但重要,可加以理解。
{
w
l
,
r
+
1
=
w
l
+
r
+
a
r
+
1
−
a
⌊
l
+
r
+
1
2
⌋
1
式
w
l
+
1
,
r
+
1
=
w
l
+
1
,
r
+
a
r
+
1
−
a
⌊
l
+
r
+
2
2
⌋
2
式
\begin{cases}w_{l,r+1}=w_{l+r}+a_{r+1}-a_{\lfloor\frac{l+r+1}{2}\rfloor}\ 1式 \\ w_{l+1,r+1}=w_{l+1,r}+a_{r+1}-a_{\lfloor\frac{l+r+2}{2}\rfloor}\ 2式 \end{cases} \\
{wl,r+1=wl+r+ar+1−a⌊2l+r+1⌋ 1式wl+1,r+1=wl+1,r+ar+1−a⌊2l+r+2⌋ 2式
2式
−
-
− 1式,得:
w
l
+
1
,
r
+
1
−
w
l
,
r
+
1
=
w
l
+
1
,
r
+
a
r
+
1
−
a
⌊
l
+
r
+
2
2
⌋
−
w
l
,
r
−
a
r
+
1
+
a
⌊
l
+
r
+
1
2
⌋
w
l
+
1
,
r
+
1
−
w
l
,
r
+
1
=
w
l
+
1
,
r
−
w
l
,
r
+
a
⌊
l
+
r
+
1
2
⌋
−
a
⌊
l
+
r
+
2
2
⌋
w
l
+
1
,
r
+
1
−
w
l
,
r
+
1
−
w
l
+
1
,
r
+
w
l
,
r
=
a
⌊
l
+
r
+
1
2
⌋
−
a
⌊
l
+
r
+
2
2
⌋
w_{l+1,r+1}-w_{l,r+1}=w_{l+1,r}+a_{r+1}-a_{\lfloor\frac{l+r+2}{2}\rfloor} -w_{l,r}-a_{r+1}+a_{\lfloor\frac{l+r+1}{2}\rfloor}\\ w_{l+1,r+1}-w_{l,r+1}=w_{l+1,r}-w_{l,r}+a_{\lfloor\frac{l+r+1}{2}\rfloor} -a_{\lfloor\frac{l+r+2}{2}\rfloor}\\ w_{l+1,r+1}-w_{l,r+1}-w_{l+1,r}+w_{l,r}=a_{\lfloor\frac{l+r+1}{2}\rfloor} -a_{\lfloor\frac{l+r+2}{2}\rfloor}
wl+1,r+1−wl,r+1=wl+1,r+ar+1−a⌊2l+r+2⌋−wl,r−ar+1+a⌊2l+r+1⌋wl+1,r+1−wl,r+1=wl+1,r−wl,r+a⌊2l+r+1⌋−a⌊2l+r+2⌋wl+1,r+1−wl,r+1−wl+1,r+wl,r=a⌊2l+r+1⌋−a⌊2l+r+2⌋
∵
\because
∵ 坐标单调上升
∴
a
⌊
l
+
r
+
1
2
⌋
≤
a
⌊
l
+
r
+
2
2
⌋
∴
a
⌊
l
+
r
+
1
2
⌋
−
a
⌊
l
+
r
+
2
2
⌋
≤
0
w
l
+
1
,
r
+
1
−
w
l
,
r
+
1
−
w
l
+
1
,
r
+
w
l
,
r
≤
0
w
l
,
r
+
w
l
+
1
,
r
+
1
≤
w
l
,
r
+
1
+
w
l
,
r
+
1
w
l
,
r
+
1
+
w
l
+
1
,
r
≥
w
l
,
r
+
w
l
+
1
,
r
+
1
\therefore\ a_{\lfloor\frac{l+r+1}{2}\rfloor}\ \le \ a_{\lfloor\frac{l+r+2}{2}\rfloor}\\ \therefore\ a_{\lfloor\frac{l+r+1}{2}\rfloor}-a_{\lfloor\frac{l+r+2}{2}\rfloor}\le 0\\ w_{l+1,r+1}-w_{l,r+1}-w_{l+1,r}+w_{l,r}\le 0\\ w_{l,r}+w_{l+1,r+1}\le w_{l,r+1}+w_{l,r+1}\\ w_{l,r+1}+w_{l+1,r}\ge w_{l,r}+w_{l+1,r+1}
∴ a⌊2l+r+1⌋ ≤ a⌊2l+r+2⌋∴ a⌊2l+r+1⌋−a⌊2l+r+2⌋≤0wl+1,r+1−wl,r+1−wl+1,r+wl,r≤0wl,r+wl+1,r+1≤wl,r+1+wl,r+1wl,r+1+wl+1,r≥wl,r+wl+1,r+1
通过四边形不等式可知,若
a
,
b
,
c
,
d
a,b,c,d
a,b,c,d 满足
a
≤
b
≤
c
≤
d
a\le b \le c \le d
a≤b≤c≤d,且
w
a
,
c
+
w
b
,
d
≤
w
a
,
d
+
w
b
,
d
w_{a,c}+w_{b,d}\le w_{a,d}+w_{b,d}
wa,c+wb,d≤wa,d+wb,d,则称
w
w
w 为四边形不等式,可以优化时间复杂度。
∵ l ≤ l + 1 ≤ r ≤ r + 1 \because l\le l+1 \le r \le r+1 ∵l≤l+1≤r≤r+1,则可以将 a , b , c , d a,b,c,d a,b,c,d 分别带入进去,即:
当
a
=
l
,
b
=
l
+
1
,
c
=
r
,
d
=
r
+
1
a=l,b=l+1,c=r,d=r+1
a=l,b=l+1,c=r,d=r+1 时:
w
l
,
r
+
1
+
w
l
+
1
,
r
≥
w
l
,
r
+
w
l
+
1
,
r
+
1
w
a
,
c
+
w
b
,
d
≥
w
a
,
d
+
w
b
,
d
w_{l,r+1}+w_{l+1,r}\ge w_{l,r}+w_{l+1,r+1}\\ w_{a,c}+w_{b,d}\ge w_{a,d}+w_{b,d}
wl,r+1+wl+1,r≥wl,r+wl+1,r+1wa,c+wb,d≥wa,d+wb,d
再附上1式
−
-
− 2式的:
w
l
,
r
+
1
−
w
l
+
1
,
r
+
1
=
w
l
,
r
−
a
r
+
1
−
a
⌊
l
+
r
+
1
2
⌋
−
w
l
+
1
,
r
+
a
r
+
1
+
a
⌊
l
+
r
+
2
2
⌋
w
l
,
r
+
1
−
w
l
+
1
,
r
+
1
=
w
l
,
r
−
a
⌊
l
+
r
+
1
2
⌋
−
w
l
+
1
,
r
+
a
⌊
l
+
r
+
2
2
⌋
w
l
,
r
+
1
−
w
l
+
1
,
r
+
1
−
w
l
,
r
+
w
l
+
1
,
r
=
a
⌊
l
+
r
+
2
2
⌋
−
a
⌊
l
+
r
+
1
2
⌋
w_{l,r+1}-w_{l+1,r+1}=w_{l,r}-a_{r+1}-a_{\lfloor\frac{l+r+1}{2}\rfloor} -w_{l+1,r}+a_{r+1}+a_{\lfloor\frac{l+r+2}{2}\rfloor}\\ w_{l,r+1}-w_{l+1,r+1}=w_{l,r}-a_{\lfloor\frac{l+r+1}{2}\rfloor}-w_{l+1,r}+a_{\lfloor\frac{l+r+2}{2}\rfloor}\\ w_{l,r+1}-w_{l+1,r+1}-w_{l,r}+w_{l+1,r}=a_{\lfloor\frac{l+r+2}{2}\rfloor} -a_{\lfloor\frac{l+r+1}{2}\rfloor}
wl,r+1−wl+1,r+1=wl,r−ar+1−a⌊2l+r+1⌋−wl+1,r+ar+1+a⌊2l+r+2⌋wl,r+1−wl+1,r+1=wl,r−a⌊2l+r+1⌋−wl+1,r+a⌊2l+r+2⌋wl,r+1−wl+1,r+1−wl,r+wl+1,r=a⌊2l+r+2⌋−a⌊2l+r+1⌋
∵
\because
∵ 坐标单调上升
∴
a
⌊
l
+
r
+
2
2
⌋
≥
a
⌊
l
+
r
+
1
2
⌋
a
⌊
l
+
r
+
2
2
⌋
−
a
⌊
l
+
r
+
1
2
⌋
≥
0
w
l
,
r
+
1
+
w
l
+
1
,
r
−
w
l
+
1
,
r
+
1
−
w
l
,
r
≥
0
w
l
,
r
+
1
+
w
l
+
1
,
r
≥
w
l
+
1
,
r
+
1
+
w
l
,
r
\therefore a_{\lfloor\frac{l+r+2}{2}\rfloor}\ge a_{\lfloor\frac{l+r+1}{2}\rfloor}\\ a_{\lfloor\frac{l+r+2}{2}\rfloor}-a_{\lfloor\frac{l+r+1}{2}\rfloor} \ge 0\\ w_{l,r+1}+w_{l+1,r}-w_{l+1,r+1}-w_{l,r}\ge 0 \\ w_{l,r+1}+w_{l+1,r} \ge w_{l+1,r+1}+w_{l,r}
∴a⌊2l+r+2⌋≥a⌊2l+r+1⌋a⌊2l+r+2⌋−a⌊2l+r+1⌋≥0wl,r+1+wl+1,r−wl+1,r+1−wl,r≥0wl,r+1+wl+1,r≥wl+1,r+1+wl,r
代码:
#include<bits/stdc++.h>
using namespace std;
const int MAXV=3003,MAXP=305,inf=1e9+5;
int v,p;
int f[MAXV][MAXP];//经过了i个村庄,正在建j个邮局
int a[MAXV],w[MAXV][MAXV],dp[MAXV][MAXP];
int minn,minid;
signed main(){
scanf("%d%d",&v,&p);
for(int i=1;i<=v;i++)
scanf("%d",&a[i]);
sort(a+1,a+v+1);
memset(f,0x3f,sizeof(f));
f[0][0]=0;
for(int i=1;i<=v;i++)
for(int j=i+1;j<=v;j++)
w[i][j]=w[i][j-1]+a[j]-a[i+j>>1];
for(int j=1;j<=p;j++)
{
dp[v+1][j]=v;
for(int i=v;i>=1;i--)
{
minn=inf;
for(int k=dp[i][j-1];k<=dp[i+1][j];k++)
{
if(f[k][j-1]+w[k+1][i]<minn)
{
minn=f[k][j-1]+w[k+1][i];
minid=k;
}
}
f[i][j]=minn;
dp[i][j]=minid;
}
}
printf("%d\n",f[v][p]);
return 0;
}