IOI2022 郵局 加強版 題解

Atserckcn發表於2024-07-27

[IOI2000] 郵局 加強版 題解

考慮動態規劃,設 \(f_{i,j}\) 為經過了 \(i\) 個村莊,正在建第 \(j\)​ 個郵局的最優距離。

以及 \(w_{i,j}\) 表示區間 \([i,j]\)​ 內建一個郵局時的距離總和。

\(a\) 陣列表示每個村莊的座標編號。

樸素版狀態轉移方程:

\[f_{i,j}=\min(f_{i,j},f_{k,j-1}+w_{k+1,i}) \\ \\ k\in [0,i) \]

根據初一上冊數學,可知在區間 \([x,y]\) 中距離所有點的距離之和最短的點為:

\(2\mid x+y\),則點位於 \(\lfloor\frac{x+y}{2}\rfloor\)

反之位於 \(\lfloor\frac{x+y+1}{2}\rfloor\)

注意到,上述狀態轉移方程,有三個未知數:\(i,j,k\)。可得時間複雜度為 \(O(PV^3)\),肯定過不了。

考慮四邊形不等式最佳化

注意到,\(w\)​ 函式的狀態轉移方程為:

\[w_{l,r+1}=w_{l,r}+a_{r+1}-a_{\lfloor\frac{l+r+1}{2}\rfloor} \]

需要簡化,過程如下,雖複雜,但重要,可加以理解。

\[\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} \\ \]

2式 \(-\) 1式,得:

\[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} \]

\(\because\) 座標單調上升

\[\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,b,c,d\) 滿足 \(a\le b \le c \le d\),且 \(w_{a,c}+w_{b,d}\le w_{a,d}+w_{b,d}\),則稱 \(w\) 為四邊形不等式,可以最佳化時間複雜度。

\(\because l\le l+1 \le r \le r+1\),則可以將 \(a,b,c,d\)​ 分別帶入進去,即:

\(a=l,b=l+1,c=r,d=r+1\) 時:

\[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} \]

再附上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} \]

\(\because\) 座標單調上升

\[\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} \]

程式碼:

#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;
}

相關文章