poj 1160 Post Office & SCAU 07校赛10320 Post Office ( dp )

来源:互联网 发布:无锡乐知英语 编辑:程序博客网 时间:2024/06/05 05:03

题意:

给出在同一直线上的v个村庄的坐标,要求建立p个邮局,使得所有村庄与离他最近的邮局的距离之和最小


参考别人的题解做的:

https://www.chenyajun.com/2010/05/27/4958

首先开一个二维数组cost,cost[i][j]表示在第i个到第j个村庄这一区间上建立 “一个”邮局时该区间上各个村庄到邮局的距离之和可以证明在(i+j)/2处建立邮局可使该区间距离之和最小(证法。。。)于是二层循环求解每个cost[i][j]再开一个二维数组res,res[i][j]表示前j个村庄建立i个邮局时的最小距离很明显有res[1][j]=cost[1][j] (1<=j<=v)然后是状态转移res[i][j](2<=i<=v,i<=j<=v) =min{ res[i-1][k] +cost[k+1][j] } (i-1<=k<=j)即“前j个村庄建立i个邮局的最小距离”等于  (对于所有合法的k){“前k个村庄建立i-1个邮局的最小距离”+ “第k+1个到第j个村庄建立“一个”邮局的最小距离”}中的最小值 



#include <cstdio>const int N=305,INF=1e9+7;int cost[N][N],res[N][N],dis[N];int main(){    int v,p,mid,min;    while(scanf("%d%d",&v,&p)>0)    {        for(int i=1;i<=v;i++)        scanf("%d",dis+i);        for(int i=1;i<=v;i++)        for(int j=1;j<=v;j++)        {            mid=(i+j)/2;            cost[i][j]=0;            for(int k=i;k<mid;k++)            cost[i][j]+=dis[mid]-dis[k];            for(int k=mid+1;k<=j;k++)            cost[i][j]+=dis[k]-dis[mid];        }        for(int i=1;i<=v;i++)        res[1][i]=cost[1][i];        for(int i=2;i<=p;i++)        for(int j=i;j<=v;j++)        {           min=INF;           for(int k=i-1;k<j;k++)           if(res[i-1][k]+cost[k+1][j]<min)           min=res[i-1][k]+cost[k+1][j];           res[i][j]=min;        }        printf("%d\n",res[p][v]);    }}



然后是SCAU_OJ 07年校赛

10320 Post Office时间限制:1000MS  内存限制:65535K提交次数:0 通过次数:0题型: 编程题   语言: 无限制DescriptionThere is a straight highway with villages alongside the highway. The highway is represented as an integer axis, and the position of each village is identified with a single integer coordinate. There are no two villages in the same position. The distance between two positions is the absolute value of the difference of their integer coordinates. Post offices will be built in some, but not necessarily all of the villages. A village and the post office in it have the same position.For building the post offices, their positions should be chosen so that the total sum of all distances between each village and its nearest post office is minimum. But there is another rule that for each village the nearest post office to it shouldn't exceed the distance of demand. Further more, the distance of demand for each village is different.You are to write a program which, given the positions of the villages, the distance of each village's demand and the number of post offices, computes the least possible sum of all distances between each village and its nearest post office. 输入格式Your program is to read from standard input. The first line contains two integers: the first is the number of villages V, 1 <= V <= 300, and the second is the number of post offices P, 1 <= P <= 30, P <= V. The second line contains V integers in increasing order. These V integers are the positions of the villages. For each position X it holds that 1 <= X <= 10000. The third line contains V integers. These V integers are the distance of demand. For each distance Y it holds that 1 <= Y <= 10000.输出格式The first line contains one integer S, which is the sum of all distances between each village and its nearest post office. If can't build post offices to satisfy the demand of all villages, output -1.输入样例10 51 2 3 6 7 9 11 22 44 5050 50 50 0 0 0 50 50 50 50输出样例20提示The five coordinates of the post offices are 6, 7, 9, 22, 50. The total sum of all distances is 20.作者admin


描述和poj基本一致,只是多了每个村庄都有一个与邮局的限制距离,在预处理和状态转移的时候进行判断即可

#include <cstdio>const int N=305,INF=1e9+7;int cost[N][N],res[N][N],dis[N],dem[N];int main(){    int v,p,mid,min,tmp,sum;    while(scanf("%d%d",&v,&p)>0)    {        for(int i=1;i<=v;i++)        scanf("%d",dis+i);        for(int i=1;i<=v;i++)        scanf("%d",dem+i);        for(int i=1;i<=v;i++)        for(int j=1;j<=v;j++)        {//            mid=(i+j)/2;//            cost[i][j]=0;//            for(int k=i;k<mid;k++)//            cost[i][j]+=dis[mid]-dis[k];//            for(int k=mid+1;k<=j;k++)//            cost[i][j]+=dis[k]-dis[mid];              min=INF;              for(mid=i;mid<=j;mid++)              {                  sum=0;                  int k;                  for(k=i;k<mid;k++)                  {                      tmp=dis[mid]-dis[k];                      if(tmp<=dem[k])                      sum+=tmp;                      else                      break;                  }                  if(k<mid)                  continue;                  for(k=mid+1;k<=j;k++)                  {                      tmp=dis[k]-dis[mid];                      if(tmp<=dem[k])                      sum+=tmp;                      else                      break;                  }                  if(k<=j)                  continue;                  if(sum<min)                  min=sum;              }              if(min==INF)              cost[i][j]=-1;              else              cost[i][j]=min;        }        for(int i=1;i<=v;i++)        res[1][i]=cost[1][i];        for(int i=2;i<=p;i++)        for(int j=i;j<=v;j++)        {           min=INF;           for(int k=i-1;k<j;k++)           if(res[i-1][k]!=-1&&cost[k+1][j]!=-1)           if(res[i-1][k]+cost[k+1][j]<min)           min=res[i-1][k]+cost[k+1][j];           if(min==INF)           res[i][j]=-1;           else           res[i][j]=min;        }        printf("%d\n",res[p][v]);    }}


原创粉丝点击