POJ 1160 Post Office

来源:互联网 发布:英语6级口语考试知乎 编辑:程序博客网 时间:2024/06/06 14:22
题意:给定n(n<=300)个在一维坐标系下的村庄,想从中挑选m(m<=30)个作为邮局,使得每个村庄到最近的邮局的距离和最小。

题解:想到dp,因为dp的值和当前状态的最后一个post office的位置有关系,开始想到dp[i][j][k]代表在前i个村庄中选择j个post office最后一个post office在位置k的
          最小花费,但是转移需要很大的时间复杂度,然后想dp[i][j]代表在前i个村庄中选择j个post office的最小花费,这样的话需要枚举最后一个office和倒数第二个
          office的管辖分界线,同时需要预处理出来在[i , j]村庄内选一个office的最小花费,将office放到(i+j)/2的位置即可。

Sure原创,转载请注明出处。

#include <iostream>#include <cstdio>#include <memory.h>using namespace std;const int inf = 1 << 29;const int maxn = 302;const int maxm = 32;int pos[maxn],sum[maxn],dp[maxn][maxm],map[maxn][maxn];int m,n;inline int MIN(int a,int b){    return a < b ? a : b;}void read(){    sum[0] = 0;    for(int i=1;i<=n;i++)    {        scanf("%d",&pos[i]);        sum[i] = sum[i-1] + pos[i];    }    return;}void make(){    for(int i=1;i<=n;i++)    {        map[i][i] = 0;        for(int j=i+1;j<=n;j++)        {            int p = (i + j) / 2;            int val = sum[j] + sum[i-1] - sum[p] * 2;            if(((i + j) & 1) == 0) val += pos[p];            map[i][j] = map[j][i] = val;        }    }    return;}void solve(){    for(int i=1;i<=n;i++)    {        dp[i][1] = map[1][i];    }    for(int i=1;i<=n;i++)    {        for(int j=2;j<=m;j++)        {            dp[i][j] = dp[i][j-1];            for(int k=1;k<i;k++)            {                dp[i][j] = MIN(dp[i][j] , dp[k][j-1] + map[k+1][i]);            }        }    }    printf("%d\n",dp[n][m]);    return;}int main(){    while(~scanf("%d %d",&n,&m))    {        read();        make();        solve();    }    return 0;}


原创粉丝点击