您的位置:首页 > 其它

POJ 1160 Post Office

2013-08-02 17:13 351 查看
题意:一条公路上有n个村庄,现在需要建造m个邮局,问邮局建造后使得所有的村庄到对应的邮局的路程总和的最小值。

思路:很水的,先自己推一下,i个村庄到j个村庄里建一个邮局,邮局所建的位置由决定于i到j之间的村庄的数量   ,如果数量为奇数的话   直接处于最中间的点,如果为偶数的话,处于最中间的2个点之间。(鉴于你不在我身边,证明略,提示一下,一层层去最外面的2个村庄)。

dis[i][j]表示i村庄到j村庄之间建个邮局,最小的路程总和。

dp[i][j]表示的是建第i个邮局,起作用的终点为第j个村庄。

状态转移方程:(邮局建立的顺序是依次建的)

                  for(int e=i;e<j;++e)

               dp[i][j] = min(dp[i][j],dp[i-1][e]+dis[e+1][j]);

#include<cstdio>
#include<cstring>
#include<iostream>
#define INF 0x3f3f3f3f
#define min(a1,b1) (a1)>(b1)?(b1):(a1)
using namespace std;
int n,m;
int arr[310];
int dp[31][301];
int dis[310][310];

void ini()
{
for(int i=1;i<=n;++i)
dis[i][i] = 0;
for(int i=1;i<n;++i)
dis[i][i+1] = arr[i+1] - arr[i];
for(int i=2;i<n;++i)
{
for(int j=1;j+i<=n;++j)
{
int ent = j+i;
dis[j][ent] = arr[ent] - arr[j] + dis[j+1][ent-1];
}
}
}

int main(void)
{
while(cin>>n>>m)
{
memset(dp,0,sizeof(dp));
for(int i=1;i<=n;++i)
scanf("%d",&arr[i]);
ini();
memset(dp,0,sizeof(dp));
for(int i=1;i<=n;++i)
dp[1][i] = dis[1][i];
for(int i=2;i<=m;++i)
{
for(int j=i;j<=n;++j)
{
dp[i][j] = INF;
if(j==i)
{
dp[i][j] = 0;
}
else
{
for(int e=i;e<j;++e)
dp[i][j] = min(dp[i][j],dp[i-1][e]+dis[e+1][j]);
}
}
}
cout<<dp[m]
<<endl;
}

return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: