V个村庄,选出P个点要求距离最短。想到dp方程,dp[i][j],表示前i个村庄中放置j个邮局所需的费用
dp[i][j] = min(dp[i][j],dp[k][j-1] + sum[k+1][j]);
sum表示i和j之间,放置一个邮局的话最小的费用,此时放到最中间为最小费用
/* poj1060 邮局选址,动态规划 */ #include <cstdio> #include <cstring> #include <iostream> #include <algorithm> #include <cmath> #define MAX 301 using namespace std; int V,P; int v[MAX],dis[MAX],sum[MAX][MAX]; int main() { while(~scanf("%d %d",&V,&P)){ for(int i = 0; i < V; i++){ scanf("%d",&v[i]); } for(int i = 0; i < V; i++){ for(int j = i; j < V; j++){ sum[i][j] = 0; int mid = (i + j)/2; for(int k = i; k <=j; k++){ sum[i][j] += abs(v[k] - v[mid]); } } } memset(dis,0x7f,sizeof(dis)); for(int i = 0; i < V; i++){ dis[i] = sum[0][i]; } for(int i = 2; i <= P; i++){ for(int j = V - 1 ;j >= i - 1 ;j--){ for(int k = i - 1 ;k < j; k++){ dis[j] = min(dis[j],dis[k] + sum[k + 1][j]); } } } printf("%d\n",dis[V - 1]); } };