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

题意:

给出在同一直线上的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

题型: 编程题   语言: 无限制
Description

There 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 5
1 2 3 6 7 9 11 22 44 50
50 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]);
    }
}

 

 

 

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章