[这是一道DP题]
dp[i][j]表示i个村庄共享j个邮局的最优距离总和
sum[i][j]表示第i个村庄到第j个村庄共享一个邮局的距离总和
dp[i][j] = min(dp[i][j], dp[k][j-1] + sum[k][i]);
p[i]表示村庄i的坐标
sum[i][j] = sum[i][j-1] + p[j] - p[(i+j)/2];
AC代码:
#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
#define min(a, b) (a) < (b) ? (a) : (b)
int dp[310][31];
int sum[310][310];
int v, p;
int pos[310];
int main(){
while(scanf("%d%d", &v, &p) != EOF){
for(int i = 1; i <= v; i++){
cin>>pos[i];
}
memset(sum, 0, sizeof(sum));
for(int i = 1; i < v; i++){
for(int j = i + 1; j <= v; j++){
sum[i][j] = sum [i][j-1] + pos[j] - pos[(i+j)/2];
}
}
for(int i = 1; i <= v; i++){
dp[i][i] = 0;
dp[i][1] = sum[1][i];
}
for(int j = 2; j <= p; j++){
for(int i = j+1; i <= v; i++){
dp[i][j]=100000;
for(int k = j - 1; k < i; k++){
dp[i][j] = min(dp[i][j], dp[k][j-1] + sum[k+1][i]);
}
}
}
printf("%d\n", dp[v][p]);
}
return 0;
}
网友评论