您的位置:首页 > 其它

poj 1160 Post Office(DP)

2014-10-31 18:13 417 查看
首先要知道一个定理就是在一个区间内如果要设置一个邮局的话,最优位置一定是最中间的村子,而且如果村子数是偶数的话,中间的两个点是等价的。

知道了这个之后,就可以N^2处理出来任一一个区间中只设置一个邮局的最小距离和。cost[i][j]表示区间村子i到村子j。

dp[i][j]表示前i个村庄中设置j个邮局之后的最小距离和。

那么转移就是dp[i][j]=min(dp[i-1][k]+cost[k+1][j]) (枚举k且k<j)

代码:

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>

using namespace std;
int V,P;
int Abs(int n){
	return n>0?n:(-n);
}
int dp[40][305];
int p[305];
int cost[305][305];
int Get(int i,int j){
    int mid=(i+j)/2;
    int sum=0;

    for(int k=i;k<=j;k++){
		sum+=Abs(p[k]-p[mid]);
    }
    return sum;
}
int main(){

	while(~scanf("%d%d",&V,&P)){
		memset(dp,0x3f,sizeof(dp));
		for(int i=1;i<=V;i++){
			scanf("%d",&p[i]);
		}
		for(int i=1;i<=V;i++){
			for(int j=i;j<=V;j++){
				cost[i][j]=Get(i,j);
				//cout<<cost[i][j]<<endl;
			}
		}
		for(int i=1;i<=V;i++){
			dp[1][i]=cost[1][i];
		}
		for(int i=2;i<=P;i++){
			for(int j=i;j<=V;j++){
				for(int k=1;k<j;k++){
					dp[i][j]=min(dp[i][j],dp[i-1][k]+cost[k+1][j]);
				}
			}
		}
		cout<<dp[P][V]<<endl;
		
	}
	return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: