[luoguP2885] [USACO07NOV]电话线Telephone Wire(DP + 贪心)

Posted 蒟蒻zht的博客

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[luoguP2885] [USACO07NOV]电话线Telephone Wire(DP + 贪心)相关的知识,希望对你有一定的参考价值。

传送门

 

真是诡异。

首先 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 }
View Code

 

以上是关于[luoguP2885] [USACO07NOV]电话线Telephone Wire(DP + 贪心)的主要内容,如果未能解决你的问题,请参考以下文章

P2885 [USACO07NOV]电话线Telephone Wire

[luoguP2886] [USACO07NOV]牛继电器Cow Relays(矩阵)

题解Luogu P2889 [USACO07NOV]挤奶的时间Milking Time

LuoguP6218 [USACO06NOV] Round Numbers S

[luoguP1879] [USACO06NOV]玉米田Corn Fields(DP)

[luoguP3092] [USACO13NOV]没有找零No Change(状压DP + 二分)