void-man

  博客园 :: 首页 :: 博问 :: 闪存 :: 新随笔 :: 联系 :: 订阅 订阅 :: 管理 ::

V个村庄,选出P个点要求距离最短。想到dp方程,dp[i][j],表示前i个村庄中放置j个邮局所需的费用

dp[i][j] = min(dp[i][j],dp[k][j-1] + sum[k+1][j]);

sum表示i和j之间,放置一个邮局的话最小的费用,此时放到最中间为最小费用

 

/*
poj1060 邮局选址,动态规划
*/
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#include <cmath>
#define MAX 301
using namespace std;
int V,P;
int v[MAX],dis[MAX],sum[MAX][MAX];
int main()
{
    while(~scanf("%d %d",&V,&P)){
        for(int i = 0; i < V; i++){
            scanf("%d",&v[i]);
        }
        for(int i = 0; i < V; i++){
            for(int j = i; j < V; j++){
                sum[i][j] = 0;
                int mid = (i + j)/2;
                for(int k = i; k <=j; k++){
                    sum[i][j] += abs(v[k] - v[mid]);
                }
            }
        }
        memset(dis,0x7f,sizeof(dis));
        for(int i = 0; i < V; i++){
            dis[i] = sum[0][i];
        }
        for(int i = 2; i <= P; i++){
            for(int j = V - 1 ;j >= i - 1 ;j--){
                for(int k = i - 1 ;k < j; k++){
                    dis[j] = min(dis[j],dis[k] + sum[k + 1][j]);
                }
            }
        }
        printf("%d\n",dis[V - 1]);

    }
};

 

posted on 2012-01-27 20:26  void-man  阅读(1199)  评论(0)    收藏  举报