BZOJ1705: [Usaco2007 Nov]Telephone Wire 架设电话线

n<=100000个杆,给高度,增加高度代价为增加量的平方,通过增加使得sigma (a[i]-a[i-1])*C,2<=i<=n的值最小。

f[i][j]--前i根杆第i根高度j的最大值,f[i][j]=min(f[i-1][k]+C*|k-j|+(j-a[i])2),过不了。

把绝对值拆掉,就有个只跟k有关的部分和只跟j有关的部分,一个用前缀转移一个用后缀转移即可。有点抽象,自行拆绝对值看。

转移时注意定义域!

于是WA了一发,原因:最后一句<=100写成<=n。

 1 #include<stdio.h>
 2 #include<string.h>
 3 #include<algorithm>
 4 #include<math.h>
 5 //#include<iostream>
 6 using namespace std;
 7 
 8 int n,C;
 9 #define maxn 100011
10 int a[maxn];int f[111],mx[111];
11 int sqr(int x) {return x*x;}
12 const int inf=0x3f3f3f3f;
13 int main()
14 {
15     scanf("%d%d",&n,&C);
16     for (int i=1;i<=n;i++) scanf("%d",&a[i]);
17     for (int i=0;i<a[1];i++) f[i]=inf;
18     for (int i=a[1];i<=100;i++) f[i]=sqr(a[1]-i);
19     for (int i=2;i<=n;i++)
20     {
21         mx[100]=f[100]+C*100;
22         for (int j=99;j>=0;j--) mx[j]=min(mx[j+1],f[j]+C*j);
23         int Min=inf;
24         for (int j=a[i-1];j<a[i];j++) Min=min(Min,f[j]-C*j);
25         for (int j=0;j<a[i];j++) f[j]=inf;
26         for (int j=a[i];j<=100;j++)
27         {
28             Min=min(Min,f[j]-C*j);
29             f[j]=min(Min+C*j,mx[j]-C*j)+sqr(j-a[i]);
30         }
31     }
32     int ans=inf;
33     for (int i=0;i<=100;i++) ans=min(ans,f[i]);
34     printf("%d
",ans);
35     return 0;
36 }
View Code
原文地址:https://www.cnblogs.com/Blue233333/p/7444611.html