话说这题很久以前就写过,然后好像一直忘了写题解……

以前看这道题还觉得挺难的,现在觉得好水

首先朴素的想法肯定是动归

f[i,j]表示到处理到第i根电线,最终高度为j的最小花费

f[i,j]:=min(f[i-1,k]+sqr(h[i]-j)+abs(j-k)*c) (h[i]<=j<=max) max为原来所有电线最高的高度

但这个会超时,我们就要想办法优化;

考虑这样一个方程式f[i,j]:=min(f[i-1,k]+sqr(h[i]-j)+(j-k)*c);

我们很容易用O(max)的时间完成转移(好像之前有过例子);

但这个方程式多了一个绝对值,根据数学上的思想,我们就去绝对值讨论呗;

容易整理得到

f[i,j]=min(min(f[i-1,k]-k*c+j*c) j>=k, min(f[i-1,k]+k*c-j*c) j<=k)+sqr(h[i]-j)

这样不难想到,令

tal[j]=min(f[i-1,k]+k*c)  k∈[j,max];

sho[j]=min(f[i-1,k]-k*c)  k∈[h[i-1],j]

tal[j]表示上一根电线杆状态高度大于当前电线杆高度j高的花费中的最小值

sho[j]表示上一根电线杆状态高度小于当前电线杆高度j高的花费中的最小值

然后弄弄就出来了

 1 const hmax=100;
 2       inf=2147483647;
 3 var h:array[0..100010] of longint;
 4     sho,tal:array[0..1010] of longint;
 5     f:array[0..1,0..1010] of longint;
 6     i,k1,k2,n,m,j,c,ans:longint;
 7 function min(a,b:longint):longint;
 8   begin
 9     if a>b then exit(b) else exit(a);
10   end;
11 
12 begin
13   readln(n,c);
14   for i:=1 to n do
15   begin
16     readln(h[i]);
17     if h[i]>m then m:=h[i];
18   end;
19   h[n+1]:=h[i];
20   k1:=1;
21   k2:=0;
22   for i:=h[1] to m do
23     f[0,i]:=sqr(i-h[1]);
24   for i:=2 to n do
25   begin
26     k1:=k1 xor 1;
27     k2:=k2 xor 1;
28     for j:=0 to m do
29     begin
30       tal[j]:=inf;
31       sho[j]:=inf;
32       f[k2,j]:=inf;
33     end;
34     tal[m]:=f[k1,m]+c*m;
35     for j:=m-1 downto h[i-1] do
36       tal[j]:=min(tal[j+1],f[k1,j]+c*j);
37     sho[h[i-1]]:=f[k1,h[i-1]]-c*h[i-1];
38     for j:=h[i-1]+1 to m do
39       sho[j]:=min(sho[j-1],f[k1,j]-c*j);
40     for j:=h[i] to m do
41       if j<h[i-1] then
42         f[k2,j]:=min(f[k2,j],tal[h[i-1]]-c*j+sqr(j-h[i]))  //注意细节,这时候上一根电线杆不存在比这根矮的状态
43       else
44         f[k2,j]:=min(f[k2,j],min(tal[j]-c*j,sho[j]+c*j)+sqr(j-h[i]));
45   end;
46   ans:=inf;
47   for i:=h[n] to m do
48     ans:=min(ans,f[k2,i]);
49   writeln(ans);
50 end.
View Code

 

posted on 2014-07-05 22:31  acphile  阅读(203)  评论(0编辑  收藏  举报