POJ 1160 四边形不等式优化DP Post Office
d(i, j)表示用i个邮局覆盖前j个村庄所需的最小花费
则有状态转移方程:d(i, j) = min{ d(i-1, k) + w(k+1, j) }
其中w(i, j)的值是可以预处理出来的。
下面是四边形不等式优化的代码:
1 #include <iostream> 2 #include <cstdio> 3 #include <algorithm> 4 #include <cstring> 5 using namespace std; 6 7 const int maxp = 30 + 10; 8 const int maxv = 300 + 10; 9 const int INF = 0x3f3f3f3f; 10 11 int n, m; 12 13 int a[maxv], sum[maxv]; 14 int d[maxp][maxv], s[maxp][maxv]; 15 16 int w(int x, int y) 17 { 18 int t = (x + y) / 2; 19 return (t-x) * a[t]-(sum[t-1]-sum[x-1]) + (sum[y]-sum[t])-(y-t)*a[t]; 20 } 21 22 int main() 23 { 24 while(scanf("%d%d", &n, &m) == 2) 25 { 26 for(int i = 1; i <= n; i++) scanf("%d", a + i); 27 for(int i = 1; i <= n; i++) sum[i] = sum[i-1] + a[i]; 28 29 memset(d, 0x3f, sizeof(d)); 30 for(int i = 1; i <= n; i++) { d[1][i] = w(1, i); s[1][i] = 0; } 31 for(int i = 2; i <= m; i++) 32 { 33 s[i][n+1] = n; 34 for(int j = n; j > i; j--) 35 { 36 for(int k = s[i-1][j]; k <= s[i][j+1]; k++) 37 { 38 if(d[i-1][k] + w(k + 1, j) < d[i][j]) 39 { 40 s[i][j] = k; 41 d[i][j] = d[i-1][k] + w(k + 1, j); 42 } 43 } 44 } 45 } 46 printf("%d\n", d[m][n]); 47 } 48 49 return 0; 50 }