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

浙公网安备 33010602011771号