P4767 [IOI 2000] 邮局 加强版

一、思路

1、暴力

先忽略数据大小,将村庄坐标按从小到大排序后,做线性DP

\(f[i][j]\) 表示在前 i 个村庄设置 j 个邮局的最小距离和

\(w(k+1,j)\) 表示在第 k+1 个村庄到第 j 个村庄设置一个邮局的最小距离和

\[f[i][j]=min_{k=0}^{i-1}f[k][j-1]+w(k+1,i) \]

当邮局的位置 \(j={{l+r}\over 2}\) 时,\(w(l,r)\) 有最小值

\(sum[i]=\sum_{j=1}^na[j]\)

\[w(l,r)=a[mid]*(mid-l+1)-(sum[mid]-sum[l-1])+(sum[r]-sum[mid])-a[mid]*(r-mid) \]

(画图理解)

2、优化 \(O(PV)\)

\(s[i][j]\) 表示 \(f[i][j]\) 的最优决策点(使 \(f[i][k]+f[k+1][j]\) 取到最小值的 k 称为 \(f[i][j]\) 的最优决策点),通过打表可以发现单调性, \(s[i][j-1] \leq s[i][j] \leq s[i+1][j]\) ,所以中间节点 k 的选取范围在 \(s[i][j-1]\)\(s[i+1][j]\) 之间

补充:

四边形不等式:对所有 \(a \leq b \leq c \leq d\) , \(w(a,d)+w(b,c)\geq w(a,c)+w(b,d)\)成立

若满足四边形不等式,则说明具有决策单调性,则 \(s[i][j-1] \leq s[i][j] \leq s[i+1][j]\)

#include<bits/stdc++.h>
#define int long long
using namespace std;
const int inf=1e9; 
int v,p,a[3005],s[3005][3005],f[3005][3005],sum[3005],mn,id;
int add(int l,int r){
	int mid=(l+r)>>1;
	return a[mid]*(mid-l+1)-(sum[mid]-sum[l-1])+(sum[r]-sum[mid])-a[mid]*(r-mid);
}
signed main(){
	ios::sync_with_stdio(0);
	cin.tie(0);
	cout.tie(0);
	cin>>v>>p;
	for(int i=1;i<=v;i++)
		cin>>a[i];
	sort(a+1,a+v+1);
	for(int i=1;i<=v;i++) 	
		sum[i]=sum[i-1]+a[i];
	memset(f,0x3f,sizeof(f));
	f[0][0]=0;
	for(int j=1;j<=p;j++){
		s[v+1][j]=v;//边界
		for(int i=v;i>=1;i--){
			mn=inf;
			for(int k=s[i][j-1];k<=s[i+1][j];k++){
				int tmp=add(k+1,i);
				if(f[k][j-1]+tmp<mn){
					mn=f[k][j-1]+tmp;
					id=k;
				}
				f[i][j]=mn;
				s[i][j]=id;
			}
		}
		
	}
	cout<<f[v][p]<<'\n';
	return 0;
}
posted @ 2026-06-14 16:41  Aguanenti  阅读(2)  评论(0)    收藏  举报