解题报告 telewire
Telewire
最近,约翰的奶牛们越来越不满足于牛棚里一塌糊涂的电话服务,于是,她们要求约翰把那些老旧的电话线换成性能更好的新电话线。新的电话线架设在已有的n根电话线杆上,第i根电话线的高度为hi,(1=<hi<=100)。电话线总是从一根电话线杆的顶端被引到相邻的那根的顶端,如果这两根电话线杆的高度hi和hj不同,那么约翰就必须支付c*abs(hi-hj)的费用,当然,你不能移动电话线杆,只能按照原有的顺序在相邻杆间架设电话线。
加高某些电话线杆能减少架设电话线的总费用,尽管这项工作也需要支付一定的费用。更准确的说,如果他把一根电话线杆加高x米的话,他需要付出x^2费用。
请你帮约翰计算一下,如果合理的进行这两项工作,他最少要在这个电话线改造工程中花多少钱。
输入说明
第一行输入两个数n和c,含义如上
接下来n行,每行一个整数hi
输出说明
输出约翰完成电话线改造工程需要花费的最小费用
输入样例
5 2
2
3
5
1
4
输出样例
15
数据范围
N<=100000
C<=100;
Hi<=100;
一个易得的方程是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)是可以用滚动数组来搞定的
具体实现是这样:用 low[j] 表示min(f[i-1,k]-k*c), high[j] 表示 min(f[i-1,k]+k*c) 。(k<=j) 然后可以预处理出 i=1 时的 low[] 和 high[] ,然后更新 f[i,j] 的时候,顺便更新一下对应的 low[] ,high[] 也就是滚动数组。
然后,代码 ???
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,i,j,k,ans:longint;
function min(a,b:longint):longint;
begin
if a<b then exit(a) else exit(b);
end;
begin
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;
filldword(f,sizeof(f)>>2,maxlongint>>2);
for i:=a[1] to 100 do
f[1,i]:=(a[1]-i)*(a[1]-i);
fillchar(low,sizeof(low),63);
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);
fillchar(high,sizeof(high),63);
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]:=min(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;
fillchar(low,sizeof(low),63);
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);
fillchar(high,sizeof(high),63);
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:=maxlongint;
for i:=down to up do
if ans>f[n,i] then ans:=f[n,i];
writeln(ans);
end.