贪心+ 动态规划。
贪心思想:当有一段连续区间[i,j]未交时,取i或j是最优的。
贪心思想证明:如果在[i,j]这段连续区间都没有被取的时候取了中间的m,那么后来一定要从m返回到i或者j,这时候是一定走了“冤枉路的”。而如果这时取了i或者j,那么到中间的时候m一定可以取。证毕。
动态规划的方程这时候就简单了:
f[i,j,0]表示[i+1,j]这一段连续区间都没有取,奶牛站在i上
f[i,j,1]表示[i,j-1]这一段连续区间都没有取,奶牛站在j上
方程:
f[i,k,0]:=Min(Max(f[i-1,k,0]+a[i]-a[i-1],time[i]),Max(f[i,k+1,1]+a[k+1]-a[i],time[i]));
f[i,k,1]:=Min(Max(f[i-1,k,0]+a[k]-a[i-1],time[k]),Max(f[i,k+1,1]+a[k+1]-a[k],time[k]));
其中,k=n,或者i=1的情况要特判一下,否则会越界。
CODE
Program POJ1991;//By_Poetshy
Const
maxn=1000;
Var
i,j,k,m,n,b,ans,tmp :Longint;
time,a :Array[1..maxn]of Longint;
f :Array[1..maxn,1..maxn,0..1]of Int64;
Function Max(i,j:Int64):Int64;
begin
if i>j then exit(i);exit(j);
end;
Function Min(i,j:Int64):Int64;
begin
if i<j then exit(i);exit(j);
end;
Procedure Qsort(l,r:Longint);
var i,j,k,temp:Longint;
begin
i:=l;j:=r;
k:=a[(i+j)>>1];
repeat
while a[i]<k do inc(i);
while a[j]>k do dec(j);
if i<=j then
begin
temp:=a[i];a[i]:=a[j];a[j]:=temp;
temp:=time[i];time[i]:=time[j];time[j]:=temp;
inc(i);dec(j);
end;
until i>j;
if i<r then Qsort(i,r);
if l<j then Qsort(l,j);
end;
BEGIN
readln(n,m,b);
for i:=1 to n do readln(a[i],time[i]);
Qsort(1,n);
f[1,n,0]:=Max(time[1],a[1]);f[1,n,1]:=Max(time[n],a[n]);
for j:=n-2 downto 0 do
for i:=1 to n-j do
begin
k:=i+j;
if k=n then
begin
f[i,k,0]:=Max(f[i-1,k,0]+a[i]-a[i-1],time[i]);
f[i,k,1]:=Max(f[i-1,k,0]+a[k]-a[i-1],time[k]);
end else if i=1 then
begin
f[i,k,0]:=Max(f[i,k+1,1]+a[k+1]-a[i],time[i]);
f[i,k,1]:=Max(f[i,k+1,1]+a[k+1]-a[k],time[k]);
end else
begin
f[i,k,0]:=Min(Max(f[i-1,k,0]+a[i]-a[i-1],time[i]),Max(f[i,k+1,1]+a[k+1]-a[i],time[i]));
f[i,k,1]:=Min(Max(f[i-1,k,0]+a[k]-a[i-1],time[k]),Max(f[i,k+1,1]+a[k+1]-a[k],time[k]));
end;
end;
ans:=Maxlongint;
for i:=1 to n do
begin
if f[i,i,0]+abs(a[i]-b)<ans then ans:=f[i,i,0]+abs(a[i]-b);
if f[i,i,1]+abs(a[i]-b)<ans then ans:=f[i,i,1]+abs(a[i]-b);
end;
writeln(ans);
END.