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]);
    }
}

 

 

 

 

 

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