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;
}



發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章