标签:
题意:有n个屋子,超人从最矮的屋子开始,依次跳下比当前屋子高且最接近当前高度的屋子(即按照屋子高度增序来跳),但超人跳跃还有一个水平距离限制D,他每次跳的水平距离<=D。现在给你每个屋子的高度是它们的相对位置,你不能改变屋子的相对位置,但是可以水平移动屋子,使得最矮的屋子和最高的屋子的水平距离最大。如果无论怎样移动,超人都无法跳到最后那个屋子则输出-1
分析:这题是个差分约束系统
首先得明白这题是要求最大值,那么就把每个不等式都转换成x-y<=k的形式,然后连一条y->x权值为k的边。
设di为第i个点的坐标。
先把每个楼的高度从小到大排个序,设num[i]为第i矮的楼对应的下标,那么可以得到d[num[i+1]]-d[num[i]]<=D
但有这个不等式很显然是不够的,那么我们很容易可以想到d[i+1]-d[i]<=D d[i]-d[i-1]<=0
那么建好图后从min(num[1],num[n])到max(num[1],num[n])的最短路就是答案了。
注意数组要开int64或long long
代码
const
maxn=1000;
var
a,b,last:array[0..maxn] of longint;
d:array[0..maxn] of int64;
v:array[1..maxn] of boolean;
state:array[1..maxn*500] of longint;
side:array[1..maxn*10] of record
x,y,z,next:longint;
end;
e,n,m,s,t,l,q:longint;
procedure qsort(l,r:longint);
var
i,j,k:longint;
begin
if l>=r then exit;
i:=l;
j:=r;
k:=a[(i+j) div 2];
repeat
while a[i]<k do inc(i);
while a[j]>k do dec(j);
if i<=j then
begin
a[0]:=a[i];a[i]:=a[j];a[j]:=a[0];
b[0]:=b[i];b[i]:=b[j];b[j]:=b[0];
inc(i);dec(j);
end;
until i>j;
qsort(i,r);
qsort(l,j);
end;
procedure add(x,y,z:longint);
begin
inc(e);
side[e].x:=x; side[e].y:=y; side[e].z:=z;
side[e].next:=last[x]; last[x]:=e;
end;
function min(x,y:longint):longint;
begin
if x<y then exit(x)
else exit(y);
end;
function max(x,y:longint):longint;
begin
if x>y then exit(x)
else exit(y);
end;
procedure init;
var
i:longint;
begin
e:=0;
fillchar(last,sizeof(last),0);
readln(n,m);
for i:=1 to n do
begin
read(a[i]);
b[i]:=i;
end;
readln;
qsort(1,n);
s:=min(b[1],b[n]);
t:=max(b[1],b[n]);
for i:=1 to n-1 do
begin
add(min(b[i],b[i+1]),max(b[i],b[i+1]),m);
add(i+1,i,-1);
add(i,i+1,m);
end;
end;
procedure spfa;
var
head,tail,i,u:longint;
begin
for i:=1 to n-1 do
if abs(b[i]-b[i+1])>m then
begin
writeln('Case ',l,': ',-1);
exit;
end;
fillchar(d,sizeof(d),$7f div 3);
d[s]:=0;
fillchar(v,sizeof(v),true);
v[s]:=false;
head:=0;
tail:=1;
state[1]:=s;
repeat
inc(head);
u:=state[head];
i:=last[u];
while i>0 do
with side[i] do
begin
if d[x]+z<d[y] then
begin
d[y]:=d[x]+z;
if v[y] then
begin
v[y]:=false;
inc(tail);
state[tail]:=y;
end;
end;
i:=next;
end;
v[u]:=true;
until head>=tail;
writeln('Case ',l,': ',d[t]);
end;
begin
readln(q);
for l:=1 to q do
begin
init;
spfa;
end;
end.
标签:
原文地址:http://blog.csdn.net/qq_33229466/article/details/51333900