您的位置:首页 > 其它

POJ 1160 Post Office

2012-08-31 20:29 344 查看
题意:给定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
[m]);
return;
}

int main()
{
while(~scanf("%d %d",&n,&m))
{
read();
make();
solve();
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: