架设电话线【usaco Nov. 07 Gold Division】

                                                                 架设电话线
最近,Farmer John的奶牛们越来越不满于牛棚里一塌糊涂的电话服务,于是,她们要求FJ把那些老旧的电话线换成性能更好的新电话线。新的电话线架设在已有的N(2 <= N <= 100,000)根电话线杆上,第i根电话线杆的高度为height_i米(1 <= height_i <= 100)。电话线总是从一根电话线杆的顶端被引到相邻的那根的顶端,如果这两根电话线杆的高度不同,那么FJ就必须为此支付C*电话线杆高度差(1 <= C <= 100)的费用。当然,你不能移动电话线杆,只能按原有的顺序在相邻杆间架设电话线。
    Farmer John认为,加高某些电话线杆能减少架设电话线的总花费,尽管这项工作也需要支出一定的费用。更准确地,如果他把一根电话线杆加高X米的话,他得为此付出X^2的费用。
    请你帮Farmer John计算一下,如果合理地进行这两种工作,他最少要在这个电话线改造工程上花多少钱。
程序名: telewire
输入格式:
* 第1行: 2个用空格隔开的整数:N和C
* 第2..N+1行: 第i+1行仅有一个整数:height_i
输入样例 (telewire.in):
5 2
2
3
5
1
4
输入说明:
一共有5根电话线杆,在杆间拉电话线的费用是每米高度差$2。在改造之前,电话线杆的高度依次为2,3,5,1,4米。
输出样例:
* 第1行: 输出Farmer John完成电话线改造工程所需要的最小花费
输出样例 (telewire.out):
15
输出说明:
    {zh0}的改造方法是:Farmer John把{dy}根电话线杆加高1米,把第四根加高2米,使得它们的高度依次为3,3,5,3,4米。这样花在加高电线杆上的钱是$5。此时,拉电话线的费用为$2*(0+2+2+1) = $10,总花费为$15。

一个易得的方程是f[i,j]表示第i个电线杆长度为j时的最小费用

f[i,j]:=min(f[i-1,k]+sqr(a[i]-j)+abs(j-k)*c);

观察方程可以转化为等价方程组

if j<=k 那么 f[i,j]:=min(f[i-1,k]+k*c)+sqr(a[i]-j)-j*c

if j>k    那么 f[i,j]:=min(f[i-1,k]-k*c)+sqr(a[i]-j)+j*c

而min(f[i-1,k]+k*c)与min(f[i-1,k]-k*c)是可以用滚动数组来搞定的

我的弱程序:({zd0}居然0.59s   TOT.........太弱了)

program telewire;

const
maxn=100001;
maxint=99999999;


var
f:array[-1..maxn,-1..101] of longint;
high,low:array[-1..100] of longint;
a:array[-1..maxn] of longint;
n,c,up,down:longint;


function min(a,b:longint):longint;
begin
if a<b then exit(a) else exit(b);
end;


procedure datain;
var
i,j:longint;
begin
assign(input,'telewire.in');reset(input);
assign(output,'telewire.out');rewrite(output);
readln(n,c);
up:=0;
down:=101;
for i:=1 to n do
begin
readln(a[i]);
if a[i]>up then up:=a[i];
if a[i]<down then down:=a[i];
end;
end;


procedure main;
var
i,j,k,ans:longint;
begin
for i:=-1 to maxn do
for j:=-1 to 101 do
    f[i,j]:=maxint;

for i:=a[1] to 100 do
f[1,i]:=(a[1]-i)*(a[1]-i);

for k:=down to up do
    low[k]:=maxint;

low[up]:=f[1,up]+up*c;

for k:=up-1 downto down do
     low[k]:=min(low[k+1],f[1,k]+k*c);

for k:=down to up do
    high[k]:=maxint;

high[down]:=f[i,down]-down*c;

for k:=down+1 to up do
     high[k]:=min(high[k-1],f[1,k]-k*c);


for i:=2 to n do
begin

for j:=a[i] to up do
    begin
    f[i,j]:=low[j]+(a[i]-j)*(a[i]-j)-j*c;
    f[i,j]:=min(f[i,j],high[j]+(a[i]-j)*(a[i]-j)+j*c);
    end;


for k:=down to up do
    low[k]:=maxint;

low[up]:=f[i,up]+up*c;

for k:=up-1 downto down do
     low[k]:=min(low[k+1],f[i,k]+k*c);

for k:=down to up do
    high[k]:=maxint;

high[down]:=f[i,down]-down*c;

for k:=down+1 to up do
     high[k]:=min(high[k-1],f[i,k]-k*c);


end;

ans:=maxint;

for i:=down to up do
if ans>f[n,i] then ans:=f[n,i];

writeln(ans);
end;


begin
datain;
main;
close(input);
close(output);
end.

- <problem title="telewire" filename="telewire.pas" status="1" hash="1230896635" detail="">
<testcase status="7" exitcode="0" detail="" time="0.06" memory="41280" score="10" />
<testcase status="7" exitcode="0" detail="" time="0.06" memory="41280" score="10" />
<testcase status="7" exitcode="0" detail="" time="0.06" memory="41280" score="10" />
<testcase status="7" exitcode="0" detail="" time="0.04" memory="41280" score="10" />
<testcase status="7" exitcode="0" detail="" time="0.09" memory="41280" score="10" />
<testcase status="7" exitcode="0" detail="" time="0.09" memory="41280" score="10" />
<testcase status="7" exitcode="0" detail="" time="0.1" memory="41280" score="10" />
<testcase status="7" exitcode="0" detail="" time="0.18" memory="41280" score="10" />
<testcase status="7" exitcode="0" detail="" time="0.34" memory="41280" score="10" />
<testcase status="7" exitcode="0" detail="" time="0.57" memory="41280" score="10" />



郑重声明:资讯 【架设电话线【usaco Nov. 07 Gold Division】】由 发布,版权归原作者及其所在单位,其原创性以及文中陈述文字和内容未经(企业库qiyeku.com)证实,请读者仅作参考,并请自行核实相关内容。若本文有侵犯到您的版权, 请你提供相关证明及申请并与我们联系(qiyeku # qq.com)或【在线投诉】,我们审核后将会尽快处理。
—— 相关资讯 ——