标签:贪心 lin abs 技术 print turn 前缀 span closed
真是诡异。
首先 O(n * 100 * 100)
三重循环
f[i][j] 表示到第 i 个柱子,高度是 j 的最小花费
f[i][j] = min(f[i - 1][k] + abs(k - j) * c + (j - a[j]) * (j - a[j]) (1 <= k <= 100)
然而肯定超时
对于f[i][j]的值,既可以从f[i-1][j+]更新,又可以从f[i-1][j]更新,还可以从f[i-1][j-]更新。
所以可以从后往前扫,从前往后扫,都记录一个前缀最小值,然后用这个更新就行。
——代码
1 #include <cstdio> 2 3 const int MAXN = 100001, INF = 100000001; 4 int n, c, temp, ans = INF; 5 int a[MAXN], f[MAXN][101]; 6 7 inline int min(int x, int y) 8 { 9 return x < y ? x : y; 10 } 11 12 int main() 13 { 14 int i, j; 15 scanf("%d %d", &n, &c); 16 for(i = 1; i <= n; i++) scanf("%d", &a[i]); 17 for(i = 1; i <= n; i++) 18 { 19 temp = INF; 20 for(j = 100; j >= a[i]; j--) 21 { 22 temp = min(temp + c, f[i - 1][j]); 23 f[i][j] = temp + (j - a[i]) * (j - a[i]); 24 } 25 temp = INF; 26 for(j = 1; j <= 100; j++) 27 { 28 temp = min(temp + c, f[i - 1][j]); 29 f[i][j] = min(f[i][j], temp + (j - a[i]) * (j - a[i])); 30 if(j < a[i]) f[i][j] = INF; 31 } 32 } 33 for(i = a[n]; i <= 100; i++) ans = min(ans, f[n][i]); 34 printf("%d\n", ans); 35 return 0; 36 }
[luoguP2885] [USACO07NOV]电话线Telephone Wire(DP + 贪心)
标签:贪心 lin abs 技术 print turn 前缀 span closed
原文地址:http://www.cnblogs.com/zhenghaotian/p/6882283.html