package pku1160;
/*在一条高速公路边上有V个村庄,用一条坐标轴来描述这条公路,每个村庄的坐标各不相同,
* 且都是整数。两个村庄间的距离用他们的坐标值差的绝对值表示。现在要在这些村庄中选
* 出P个建立邮局,邮局建立在村庄里,每个村庄使用离他最近的那个邮局。求一种建设方案,
* 使得所有村庄到各自所使用的邮局的距离总和最小。
*
* 算法: 动态规划 */
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 | import java.util.*; public class Main { /*Cost[j,i]表示安排前i个邮局给前j个村庄使用 * D[i,j]表示在第i个到第j个村庄中建立一个邮局得到的最短距离总和。 * D[a,b]可以利用关系式d[a,a]=0, D[a,b]=D[a,b-1]+x[b]-x[(a+b)/2]表示*/ public static void main(String[] args) { // TODO Auto-generated method stub Scanner cin = new Scanner(System.in); int n, m; n = cin.nextInt(); m = cin.nextInt(); int[] x = new int[n + 1]; int[][] d = new int[n + 2][n + 2]; int[][] cost = new int[n + 2][n + 2]; for (int i = 1; i <= n; i++) x[i] = cin.nextInt(); for (int i = 1; i <= n; i++){ for (int j = 1; j <= n; j++){ if (i >= j) d[i][j] = 0; else d[i][j] = d[i][j - 1] + x[j] - x[(i + j) / 2]; } } for (int i = 1; i <= n; i++) cost[i][1] = d[1][i]; for (int i = 2; i <= m; i++ ){ for (int j = i + 1; j <= n; j++){ int tmp = Integer.MAX_VALUE; for (int k = i - 1; k <= j; k++){ if ( tmp > cost[k][i - 1] + d[k + 1][j] ) tmp = cost[k][i - 1] + d[k + 1][j]; // Cost[n,m] = min{Cost[i,m-1]+D[i+1,n]},i=m-1,m,…,n-1。 } cost[j][i] = tmp; } } System.out.println(cost[n][m]); } } |