poj1160 Post Office

输入:

10 5
1 2 3 6 7 9 11 22 44 50
意为有10个小村,有5个邮局,放置邮局使得所有小村到最近的邮局的距离之和最小

小村的坐标为1,2,3,6,7,9,11,22,44,50

定义状态:

dp[i][j]表示[0,i]这i+1个小村放置j个邮局的最小指

状态转移:

dp[i][j]=dp[k][j-1]+L[k+1][i]               L[i][j]表示[i,j]放置一个邮局时的最小指,0<=k<i

代码:

#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std;
int dp[330][40];//dp[i][j]表示0,,,i个村庄j个邮局的最小值
int L[330][330];//L[i][j]表示[i,j]一个邮局的最小值
int village[330];
void Run(int i,int j)
{
	int mid=(i+j)/2;
	L[i][j]=0;
	for(int k=i;k<=j;k++)
	{
		L[i][j]+=abs(village[mid]-village[k]);
	}
}
void RunDp(int i,int j)//求dp[i][j]   [0,i]
{
	if(j==1)
	{
		if(L[0][i]==-1)
		{
			Run(0,i);
		}
		dp[i][j]=L[0][i];
		return;
	}
	if(i==0)
	{
		if(j>=1)
		{
			dp[i][j]=0;
		}
		return;
	}
	for(int k=0;k<i;k++)
	{
		if(dp[k][j-1]==-1)
		{
			if(k==0&&j==1)
			{
				k=0;
			}
			RunDp(k,j-1);
		}
		if(L[k+1][i]==-1)
		{
			Run(k+1,i);
		}
		if(dp[i][j]==-1||dp[i][j]>dp[k][j-1]+L[k+1][i])
		{
			dp[i][j]=dp[k][j-1]+L[k+1][i];
		}
	}
}
int main()
{
	int V,P;
	while(~scanf("%d%d",&V,&P))
	{
		memset(dp,-1,sizeof(dp));
		memset(L,-1,sizeof(L));
		for(int i=0;i<V;i++)
		{
			scanf("%d",&village[i]);
		}
		RunDp(V-1,P);
		printf("%d\n",dp[V-1][P]);
	}
	return 0;
}



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