村庄之间建立邮局 - 区间 dp
There is a straight highway with villages alongside the highway. The highway is represented as an integer axis, and the position of each village is identified with a single integer coordinate. There are no two villages in the same position. The distance between two positions is the absolute value of the difference of their integer coordinates.
Post offices will be built in some, but not necessarily all of the villages. A village and the post office in it have the same position. For building the post offices, their positions should be chosen so that the total sum of all distances between each village and its nearest post office is minimum.
You are to write a program which, given the positions of the villages and the number of post offices, computes the least possible sum of all distances between each village and its nearest post office.
Input
Post offices will be built in some, but not necessarily all of the villages. A village and the post office in it have the same position. For building the post offices, their positions should be chosen so that the total sum of all distances between each village and its nearest post office is minimum.
You are to write a program which, given the positions of the villages and the number of post offices, computes the least possible sum of all distances between each village and its nearest post office.
Your program is to read from standard input. The first line
contains two integers: the first is the number of villages V, 1 <= V
<= 300, and the second is the number of post offices P, 1 <= P
<= 30, P <= V. The second line contains V integers in increasing
order. These V integers are the positions of the villages. For each
position X it holds that 1 <= X <= 10000.
Output
The first line contains one integer S, which is the sum of all
distances between each village and its nearest post office.
Sample Input
10 5 1 2 3 6 7 9 11 22 44 50Sample Output
9
题意:在一条直线上面有 n 个村子,在一些村子上面建立邮局,求所有村子到最近的邮局的最小花费总和
思路分析:
一道经典的dp问题
首先想一个问题,在任意一段区间上面如果我只建立一个村子,怎么建才会使花费最小呢?显然是应该建立在区间的中点的位置处,即(a+b)/2,的位置上,这里就存在一个小问题,就是当区间上的点若为奇数个时,此时最优的点是只有一个的,但当区间的点上有偶数个时,此时最优的点会是正中间的两个。
基于这层关系,我们便可以 n^2的预处理出来任意两个村子间建立一个邮局的最小花费, dis[i][j] = dis[i][j-1]+d[j]-d[(i+j)/2]。
然后考虑 dp, 先选取状态, dp[i][j]表示到第 i 个村子是时已经建立了 j 个邮局的最小花费,dp[i][j] = min(dp[i][j], dp[k][j-1]+dis[k+1][i])
代码示例:(未测试,poj炸了。。)
int n, m; int d[305]; int dis[305][305], dp[305][305]; int main() { //freopen("in.txt", "r", stdin); //freopen("out.txt", "w", stdout); cin >> n >> m; for(int i = 1; i <= n; i++){ scanf("%d", &d[i]); } for(int i = 1; i <= n; i++){ for(int j = i+1; j <= n; j++){ dis[i][j] = dis[i][j-1]+d[j]-d[(i+j)/2]; } } memset(dp, inf, sizeof(dp)); for(int i = 1; i <= n; i++) { dp[i][1] = dis[1][i]; dp[i][i] = 0; } for(int i = 3; i <= n; i++){ for(int j = 2; j <= min(i, m); j++){ for(int k = j-1; k < i; k++){ dp[i][j] = min(dp[i][j], dp[k][j-1]+dis[k+1][i]); printf("%d %d %d\n", i, j, dp[i][j]); } } } printf("%d\n", dp[n][m]); return 0; }
东北日出西边雨 道是无情却有情