PKU 1160 Post Office

作者在 2008-05-11 21:09:00 发布以下内容

http://acm.pku.edu.cn/JudgeOnline/problem?id=1160

DP题

在一条笔直的公路上有一排城镇,要在城镇上建邮局,首先输入城镇数和要建的邮局数,问:所有城镇距离最近邮局的距离总和是多少?

题目思路:用w[i][j]记录把前i个邮局建到前j个村庄中的最优解,用distance[i][j]记录所有在ij村庄中,建1个邮局的最小代价。显然邮局应该设到中点。让前i个邮局覆盖前j个村庄,第i+1个邮局覆盖第j+1j+k个村庄(j+k<=n),则状态转移方程为
w[i+1][j+k]=min{w[i][j]+distance[j+1][j+k];} (k+j<=n)。distance数组存放从ij中有一个邮局的最小代价,显然该邮局应该放在中间。Opt[i][j] 表示前i个邮局覆盖前j个村庄的最小代价,对于i=1来说,w[i][j] = distance[i][j],让前2个邮局覆盖前j个村庄,也就是i=2的情况,可能是一下情况的最优解:第一个邮局覆盖第一个村庄,第二个村庄覆盖2-j个村庄,或者第一个邮局覆盖第1-2个村庄,第二个村庄覆盖3-j个村庄,第一个邮局覆盖第1-3个村庄,第二个村庄覆盖4-j个村庄

#include<stdio.h>
#include<string.h>
int distance[310][310];
int w[310][310];
#define max 3000000
int main()
{
    int i,j,k,m,n,middle,q,v[310];
 while(scanf("%d%d",&m,&n)!=EOF)
 {
  for(i=1;i<=m;i++)
   scanf("%d",&v[i]);
  memset(distance,0,sizeof(distance));
  for(i=1;i<=m;i++)
   for(j=i;j<=m;j++)                     
   {
    middle=(i+j)/2;
    for(k=i;k<=middle;k++)
     distance[i][j]=distance[i][j]+v[middle]-v[k];
    for(k=middle+1;k<=j;k++)
     distance[i][j]=distance[i][j]+v[k]-v[middle];
   }
  for(i=0;i<=n;i++)
   for(j=0;j<=m;j++)
    w[i][j]=max;
  w[0][0]=0;
  for(i=0;i<=n;i++)
   for(j=0;j<=m;j++)
    if(w[i][j]<max)
    {
     for(k=1;k<=m-j;k++)
     {
      q=w[i][j]+distance[j+1][j+k];
      if(w[i+1][j+k]>q)
       w[i+1][j+k]=q;
     }
    }
  printf("%d\n", w[n][m]);
 }
 return 0;
}

ACM | 阅读 5358 次
文章评论,共0条
游客请输入验证码
最新评论