poj 1160

题意为给出n个村庄的坐标,问如何设立m个邮局,使得每个村庄离其最近邮局的总路程即总花费最小。

思路:

若只设立一个邮局,可知邮局设在村庄坐标中位数的位置是最优解。这个问题属于在n个东西中选出m个,求全局最优解的问题。自然想到dp。设立二维数组dp[i][j-1]表示i个邮局放入前j个村庄所需的最小费用。可得dp方程:dp[i][j]=min(dp[i-1][k]+cost[k+1][j]) (i-1<=k<j)。cost[i][j]表示在村庄i到村庄j之间选一个村庄设立邮局的最小花费,即为村庄[i,j]中每个村庄到ij中位数村庄的距离和,可预处理得到.。转移方程的意义上是:枚举前i-1个邮局所占有的村庄区间,即为0到k,剩余的一个邮局在区间k+1到j,其最小花费为cost[i][j]。所有k种组合的最小值即为dp[i][j]的值。

cost 数组求解的过程中也存在一个递推式:cost[i][j]=cost[i][j-1]+vl[j]-vl[(i+j)/2],其中vl[i]表示第i+1个村庄的坐标。纸上画一画可知其正确性。

注意:dp[1][j]=cost[0][j]的初始化

#include <cstdio>
using namespace std;
int dp[31][301];
int cost[301][301];
int vl[301];
int v,p;
int main()
{
	scanf("%d%d",&v,&p);
	for(int i=0;i<v;i++)
		scanf("%d",vl+i);
	for(int i = 0; i < v-1; ++i)
		for(int j=i+1;j<v;++j)
			cost[i][j]=cost[i][j-1]+vl[j]-vl[(i+j)/2];//预处理得到cost数组的值
	for(int i=1;i<v;i++)
		dp[1][i]=cost[0][i];//dp初始化
	for(int i=2;i<=p;i++)
		for(int j=i;j<v;j++)
		{
			int t=dp[i-1][i-1]+cost[i][j];
			for(int k=i;k<j;k++)
				if(dp[i-1][k]+cost[k+1][j]<t)
					t=dp[i-1][k]+cost[k+1][j];
			dp[i][j]=t;
		}
	printf("%d\n",dp[p][v-1]);
	return 0;
}



  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值