题目描述
多瑞卡得到了一份有趣而高薪的工作。每天早晨他必须关掉他所在村庄的街灯。所有的街灯都被设置在一条直路的同一侧。
多瑞卡每晚到早晨5点钟都在晚会上,然后他开始关灯。开始时,他站在某一盏路灯的旁边。
每盏灯都有一个给定功率的电灯泡,因为多端卡有着自觉的节能意识,他希望在耗能总数最少的情况下将所有的灯关掉。
多端卡因为太累了,所以只能以1m/s的速度行走。关灯不需要花费额外的时间,因为当他通过时就能将灯关掉。
编写程序,计算在给定路灯设置,灯泡功率以及多端卡的起始位置的情况下关掉所有的灯需耗费的最小能量。
输入格式
输入文件的第一行包含一个整数N,2≤N≤1000,表示该村庄路灯的数量。
第二行包含一个整数V,1≤V≤N,表示多瑞卡开始关灯的路灯号码。
接下来的N行中,每行包含两个用空格隔开的整数D和W,用来描述每盏灯的参数,其中0≤D≤1000,0≤W≤1000。D表示该路灯与村庄开始处的距离(用米为单位来表示),W表示灯泡的功率,即在每秒种该灯泡所消耗的能量数。路灯是按顺序给定的。
输出格式
输出文件的第一行即唯一的一行应包含一个整数,即消耗能量之和的最小值。注意结果小超过1,000,000,000。
样例输入
4
3
2 2
5 8
6 1
8 7
样例输出
56
//------------------------------------------------------------------------------------
分析:用g[i,j]表示除了i~j(包括i,j)之间的灯,其它的灯的功率总和.
f[i,j,0]表示关完i~j之间的等停在I的最小值,
f[i,j,1]表示关完i~j之间的等停在J的最小值.
初始时f[v,v,0]=0,f[v,v,1]=0;
转移方程很好写:
f[i,j,0]=min(f[i+1,j,0]+g[i+1,j]*(d[i+1]-d[i]),f[i+1,j,1]+g[i+1,j]*(d[j]-d[i]))
f[i,j,1]同理.
code:
const oo=10000000000000000;
var f:array[0..1001,0..1001,0..1] of int64;
g:array[0..1001,0..1001] of longint;
d,w,s:array[0..1001] of longint;
n,v,i,j:longint;
function min(a,b:int64):int64;
begin
if a>b then exit(b); exit(a)
end;
begin
readln(n);
readln(v);
for i:=1 to n do
begin
readln(d[i],w[i]);
s[i]:=s[i-1]+w[i];
end;
for i:=1 to n do
for j:=i to n do g[i,j]:=s[i-1]+s[n]-s[j];
for i:=0 to 1001 do
for j:=0 to 1001 do
begin
f[i,j,0]:=oo;
f[i,j,1]:=oo;
end;
f[v,v,0]:=0; f[v,v,1]:=0;
for j:=v to n do
for i:=j-1 downto 1 do
begin
f[i,j,0]:=min(f[i+1,j,0]+g[i+1,j]*(d[i+1]-d[i]),
f[i+1,j,1]+g[i+1,j]*(d[j]-d[i]));
f[i,j,1]:=min(f[i,j-1,0]+g[i,j-1]*(d[j]-d[i]),
f[i,j-1,1]+g[i,j-1]*(d[j]-d[j-1]));
end;
writeln(min(f[1,n,0],f[1,n,1]));
end.