Poj Post Office 【DP】经典邮局问题
http://poj.org/problem?id=1160
经典邮局问题
f[i][j]表示前i个邮局建在前j个村庄时的最小距离;dis[i][j],表示有1个邮局在村庄i与j之间时,村庄i至村庄j到邮局的最短距离总和
#include <cstdio> #include <cstring> #include <iostream> #include <algorithm> #include <vector> #include <set> #include <map> #include <cmath> #include <queue> using namespace std; template <class T> void checkmin(T &t,T x) {if(x < t) t = x;} template <class T> void checkmax(T &t,T x) {if(x > t) t = x;} template <class T> void _checkmin(T &t,T x) {if(t==-1) t = x; if(x < t) t = x;} template <class T> void _checkmax(T &t,T x) {if(t==-1) t = x; if(x > t) t = x;} typedef pair <int,int> PII; typedef pair <double,double> PDD; typedef long long ll; #define foreach(it,v) for(__typeof((v).begin()) it = (v).begin(); it != (v).end ; it ++) const int N = 330; int x[N] , n , p , f[N][N] , dis[N][N]; void init() { memset(dis,0,sizeof(dis)); for(int i=1;i<=n;i++) for(int j=i+1;j<=n;j++) { int m = (i+j) >> 1; for(int k=i;k<=j;k++) dis[i][j] += abs(x[k]-x[m]); } } void solve() { for(int i=2;i<=n;i++) f[1][i] = dis[1][i]; for(int i=2;i<=p;i++) for(int j=1;j<=n;j++) f[i][j] = (1<<29); for(int i=2;i<=p;i++) for(int j=i;j<=n;j++) for(int k=i;k<=j;k++) checkmin(f[i][j],f[i-1][k]+dis[k+1][j]); } int main() { int cas = 1; while(~scanf("%d%d",&n,&p) && n+p) { printf("Chain %d\n" , cas ++); for(int i=1;i<=n;i++) scanf("%d",&x[i]); sort(x , x+n); init(); solve(); printf("Total distance sum = %d\n\n" , f[p][n]); } return 0; }