Luogu P4767「IOI2000」邮局

P4767「IOI2000」邮局

显然 DP ,考虑设 (f_{i,j}) 表示前 (j) 个村庄放了 (i) 个邮局的最小距离,为了方便 DP ,我们钦定这个区间里的村庄都匹配这些邮局。

那么转移式写出来就是 :

[f_{i,j} = min_{k=1}^{j-1} left{ f_{i,k-1} + w(k+1,j) ight} ]

其中, (w(l,r)) 表示区间 (left[ l,r ight]) 中放一个邮局的贡献,由初中知识可知取最中间的村庄放置邮局一定最优。
那么就有:

[w(l,r) = w(l,r-1) + X_{r} - X_{lfloor frac{l+r}{2} floor} ]

显然, $ w $ 是满足四边形不等式和区间包含单调性的。

[ ext{设 } l_1 le l_2 le r_1 le r_2 ,\ ext{则 } w(l_1,r_1) + w(l_2,r_2) = sum_{i=1}^{lfloor frac{l_1+r_1}{2} floor} left( X_{r_1-i+1} - X_{i} ight) + sum_{i=1}^{lfloor frac{l_2+r_2}{2} floor} left( X_{r_2-i+1} - X_{i} ight) ,\ w(l_1,r_2) + w(l_2,r_1) = sum_{i=1}^{lfloor frac{l_1+r_2}{2} floor} left( X_{r_2-i+1} - X_{i} ight) + sum_{i=1}^{lfloor frac{l_2+r_1}{2} floor} left( X_{r_1-i+1} - X_{i} ight) ,\ ]

对比这两个式子,发现加的项和减的项数量都分别相同,观察项数的分配,发现,在第二个式子中,加的项更集中于靠近 (r_2) ,减的项更集中于 (l_1) ,所以符合四边形不等式。

然后 ,根据套路 (g_{i-1,j} le g_{i,j} le g_{i,j+1}) ,倒序跑 DP 即可,时间复杂度 (O(VP))
其中 (g_{i,j}) 表示 (f_{i,j}) 的最小最优决策点。

#include<bits/stdc++.h>
#define fo(i,a,b) for(int i=a;i<=b;++i)
#define fd(i,a,b) for(int i=a;i>=b;--i)
using namespace std;
const int N=3010;
const int M=310;
int f[N][M],n,m,w[N],g[N][N],fr[N][M];
bool cmp(int a,int b){return a<b;}
int main(){
	scanf("%d%d",&n,&m);
	fo(i,1,n)scanf("%d",&w[i]);
	sort(w+1,w+n+1,cmp);
	fo(i,1,n){
		fo(j,i+1,n)
			g[i][j]=g[i][j-1] + w[j] - w[(i+j)/2];
	}
	memset(f,127,sizeof(f));
	f[0][0]=0;
	fo(j,1,m){
		fr[n+1][j]=n;
		fd(i,n,1){
			fo(r,fr[i][j-1],fr[i+1][j]){
				int tmp=f[r][j-1] + g[r+1][i];
				if(tmp<f[i][j]){
					f[i][j]=tmp;
					fr[i][j]=r;
				}
			}
		}
	}
	printf("%d
",f[n][m]);
	
	return 0;
}
原文地址:https://www.cnblogs.com/Kelvin2005/p/15181982.html