题意:有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.