ACM PKU 1160 Post Office http://acm.pku.edu.cn/JudgeOnline/problem?id=1160

来之不易呀!!!

用opt[i][j]记录把前i个邮局建到前j个村庄中的最优解
用cost[i][j]记录所有在i到j村庄中,建1个邮局的最小代价。显然邮局应该设到中点。

让前i个邮局覆盖前j个村庄,第i+1个邮局覆盖第j+1至j+k个村庄(j+k<=n),则状态转移方程为
opt[i+1][j+k]=min{opt[i][j]+cost[j+1][j+k];} (k+j<=n)

#include <iostream>
using namespace std;

const int MAX = 3000000;

long cost[301][301];

long opt[301][301];

int dis[301];

int main ()
{ 
int v, p_o ;
int i = 1, j , k ; 

    //memset (cost,0,sizeof(cost));

cin >> v >> p_o;

for (i = 1; i <= v; i++ )
   cin >> dis[i];


    for (i = 1 ; i <= v ; i++)
   for (j = i; j <= v ; j++)
   {
    cost[i][j] = 0;
   
    int mid = (i + j)/2;
   
    for (k = mid + 1; k <= j; k++)
    {
     cost[i][j] += dis[k] - dis[mid] ;    
    }
   
    for (k = i ; k <= mid ; k++)
    {
     cost[i][j] += dis[mid] - dis[k] ;    
    }        
   }


   for (i = 0 ; i <= p_o; i++)
   
    for (j = 0; j <= v ; j++)
    {
     opt[i][j] = MAX;
    }
重点看看这里:
   opt[0][0] = 0;
   
    for (i = 0 ; i <= p_o; i++)
    
     for (j = 0; j <= v ; j++)
     {
       for (k = 1; k + j <= v; k++)     
        if ( opt[i+1][j+k] > opt[i][j] + cost[j+1][j+k])
        {
            opt[i+1][j+k] = opt[i][j] + cost[j+1][j+k];
        }
     }
    
     cout<<opt[p_o][v]<<endl;
     return 0;
}

posted on 2011-05-06 19:03  _Clarence  阅读(146)  评论(0编辑  收藏  举报

导航