【四边形】POJ 1160 Post Office
题意:用数轴描述一条高速公路,有N个村庄,每一个村庄坐落在数轴的某个点上,需要选择P个村庄在其中建立邮局,要求每个村庄到最近邮局的距离和最小
思路:用f[i][j]表示建好i个邮局时覆盖到第j个村庄的最优解,那么就可以得到f[i][j]=min{f[i-1][k]+w[k+1][j]}(k<j),其中w[x][y]表示建一个邮局覆盖x到y的村庄的距离和
代码:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#include<stdio.h> #include<string.h> #define MAXD 310 #define MAXP 40 #define INF 0x3f3f3f3f int N, P, f[MAXD][MAXD], A[MAXD], a[MAXD], K[MAXD][MAXD]; void init(){ int i, j, k; A[0] = 0; for(i = 1; i <= N; i ++){ scanf("%d", &a[i]); A[i] = A[i - 1] + a[i]; } } int getw(int x, int y) { int t = (x + y) / 2; return A[y] - A[t] - (y - t) * a[t] - (A[t - 1] - A[x - 1] - (t - x) * a[t]); } void solve() { int i, j, k, p, t; for(i = 0; i <= N; i ++) { f[i][i] = 0; K[i][i] = i; } for(p = 1; p <= N - P; p ++) { for(i = 0; (j = i + p) <= N; i ++) f[i][j] = INF; for(i = 1; (j = i + p) <= N; i ++) { for(k = K[i][j - 1]; k <= K[i + 1][j]; k ++) if((t = f[i - 1][k - 1] + getw(k, j)) < f[i][j]) { f[i][j] = t; K[i][j] = k; } } } printf("%d\n", f[P][N]); } int main(){ while(scanf("%d%d", &N, &P) == 2) { init(); solve(); } return 0; }