1507. [IOI2000]邮局
★☆ 输入文件:postoffice.in
输出文件:postoffice.out
简单对比
时间限制:1 s 内存限制:256 MB
【题目描述】
有一条笔直的高速公路,路旁分布着一些村庄。公路可以用一条数轴表示,则村庄的位置就是其坐标。没有两个村庄的坐标相同。两个村庄之间的距离就是它们坐标之差的绝对值。
一些——但不一定是所有的村庄将修建邮局。邮局和该邮局所在的村庄处于同一位置。应当仔细选择邮局的位置,使得所有村庄到最近邮局的距离总和最短。
你要编写一个程序,给出所有村庄的坐标和计划修建的邮局个数,计算所有村庄到最近邮局的距离总和的最小可能值。
【输入格式】
输入文件的第一行有2个正整数:村庄数V(1<=V<=300),邮局数P(1<=P<=30),P<=V。
第二行有V个正整数,分别代表N个村庄的坐标。坐标的范围是[1,10000],坐标按递增顺序给出。
【输出格式】
输出一行一个正整数S,即所有村庄到最近邮局的距离总和的最小可能值。
【样例输入】
10 5
1 2 3 6 7 9 11 22 44 50
【样例输出】
9
【提示】
对于30%的数据,1<=P<=N<=10.
对于100%的数据,1<=P<=30,1<=N<=300,P<=N.
/* f[i][j]表示一直到第i个点,建了j站的最优值 dis[i][j]表示若使在i-j中选某点建站,这个点到i-j中每个点距离和的最小值 */ #include<cstdio> #include<cstring> #include<iostream> #define FRE(name) freopen(#name".in","r",stdin);freopen(#name".out","w",stdout); using namespace std; const int N=305; int n,p,a[N],f[N][N],dis[N][N]; int main(){ memset(f,0x3f3f3f3f,sizeof f); scanf("%d%d",&n,&p); for(int i=2;i<=n;i++) scanf("%d",&a[i]); for(int i=1;i<=n;i++){ for(int j=i+1;j<=n;j++){ dis[i][j]=dis[i][j-1]+a[j]-a[i+j>>1]; //贪心:(显然)选i-j的中点是建站是最优的 } } for(int i=1;i<=p;i++) f[i][i]=0; for(int i=1;i<=n;i++) f[i][1]=dis[1][i]; for(int j=2;j<=p;j++){//枚举建站的数量 for(int i=j+1;i<=n;i++){ for(int k=j-1;k<i;k++){ f[i][j]=min(f[i][j],f[k][j-1]+dis[k+1][i]);//枚举把站建在j-1到i的情况 } } } printf("%d ",f[n][p]); return 0; }