POJ1160 Post Office 动态规划

题目大意:一条直线上有n个村庄,定义村庄之间的距离为两个村庄坐标的绝对值,要在这n个村庄当中建立m个邮局,每个村庄只能使用离其最近的邮局,求出使所有村庄都使用邮局所需走的最短距离。

我们都知道只有一个邮局的情况,那么这个邮局肯定在正中间,这样才能使所有村庄到这点的距离之和最短;现在有m个邮局,我们定义一个二维数组tmp(i,j)来表示在第i个村庄到第j个村庄之间有一个邮局时的最短距离和,定义dp(i,j)来表示前i个村庄用j个邮局的最短距离和,对于当前每次增加村庄数目(i++),我们找出当前村庄下从有j-1个村庄到i-1个村庄的所有情况中 使用j-1个邮局能距离和最短的那个村庄的个数k,那么当前状态和上一个状态间的关系就可以表示为:

dp(i,j)=min(dp(i,j),dp(k,j-1)+tmp(k+1,i));

#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>
using namespace std;
#define MAX 310
int dp[MAX][MAX],tmp[MAX][MAX],ans[MAX];
int main()
{
    int n,m;
    int i,j,k;
    while(scanf("%d%d",&n,&m)!=-1)
    {
        for(i=1;i<=n;i++)
          scanf("%d",&ans[i]);
        memset(tmp,0,sizeof(tmp));
        for(i=1;i<=n;i++)
          for(j=i+1;j<=n;j++)
            for(k=i;k<=j;k++)
              tmp[i][j]+=abs(ans[(i+j)/2]-ans[k]);
        memset(dp,0x1f,sizeof(dp));
        for(i=1;i<=n;i++)
          dp[i][1]=tmp[1][i];
        for(j=2;j<=m;j++)
          for(i=j;i<=n;i++)
            for(k=j-1;k<i;k++)
              dp[i][j]=min(dp[i][j],dp[k][j-1]+tmp[k+1][i]);
        printf("%d\n",dp[n][m]);
    }
    return 0;
}


 

你可能感兴趣的:(POJ1160 Post Office 动态规划)