P2885 [USACO07NOV]电话线Telephone Wire

给出若干棵树的高度,你可以进行一种操作:把某棵树增高h,花费为h*h。

操作完成后连线,两棵树间花费为高度差*定值c。

求两种花费加和最小值。

输入输出格式

输入格式:
Line 1: Two space-separated integers: N and C

Lines 2..N+1: Line i+1 contains a single integer: heighti
输出格式:
Line 1: The minimum total amount of money that it will cost Farmer John to attach the new telephone wire.
输入输出样例

输入样例#1:
5 2
2
3
5
1
4
输出样例#1:
15
当你自信满满的推出方程式,然后打上去光荣的过了样例,最后光荣的TLE
70分的方程比较好推,O(n*h*h)(方程不推了)
然后多画一会(然而本蒟蒻画不出来orz)就会发现,对于每一个i的转移都是一个开口向上的二次函数,所以可以比较它的值,发现值开始变大的时候就可以退出了。(复杂度不明)

Pascal代码如下:

program df;
const p=1000000007;
var i,j,n,m,x,y,z,k,t,hmax,ans,sq:longint;
f:array[0..100000,0..100] of longint;
a:array[0..100000] of longint;
function min(x,y:longint):longint;
begin
if x>y then exit(y)
else exit(x);
end;

begin
readln(n,m);
for i:=1 to n do
begin
readln(a[i]);
if a[i]>hmax then hmax:=a[i];
end;
fillchar(f,sizeof(f),$7f);
for i:=a[1] to hmax do
f[1,i]:=sqr(i-a[1]);
for i:=2 to n do
for j:=a[i] to hmax do
begin
z:=p;  sq:=sqr(j-a[i]);
for k:=a[i-1] to hmax do
begin
y:=f[i-1,k]+m*abs(j-k)+sq;
if y>z then break;
z:=y;
end;
if z<f[i,j] then f[i,j]:=z;
end;

ans:=maxlongint;
for i:=a[n] to hmax do
if ans>f[n,i] then ans:=f[n,i];
writeln(ans);
end.
posted @ 2017-10-30 16:02  Gxyhqzt  阅读(130)  评论(0编辑  收藏  举报