传说中,南极有一片广阔的冰原,在冰原下藏有史前文明的遗址。整个冰原被横竖划分成了很多个大小相等的方格。在这个冰原上有N个大小不等的矩形冰山,这些巨大的冰山有着和南极一样古老的历史,每个矩形冰山至少占据一个方格,且其必定完整地占据方格。冰山和冰山之间不会重叠,也不会有边或点相连。以下两种情况均是不可能出现的:
ACM探险队在经过多年准备之后决定在这个冰原上寻找遗址。根据他们掌握的资料,在这个冰原上一个大小为一格的深洞中,藏有一个由史前人类制作的开关。而唯一可以打开这个开关的是一个占据接近一格的可移动的小冰块。显然,在南极是不可能有这样小的独立冰块的,所以这块冰块也一定是史前文明的产物。他们在想办法把这个冰块推到洞里去,这样就可以打开一条通往冰原底部的通道,发掘史前文明的秘密。冰块的起始位置与深洞的位置均不和任何冰山相邻。
这个冰原上的冰面和冰山都是完全光滑的,轻轻的推动冰块就可以使这个冰块向前滑行,直到撞到一座冰山就在它的边上停下来。冰块可以穿过冰面上所有没有冰山的区域,也可以从两座冰山之间穿过(见下图)。冰块只能沿网格方向推动。
请你帮助他们以最少的推动次数将冰块推入深洞中。
输入格式
输入文件第一行为冰山的个数N (1<=N<=4000),第二行为冰块开始所在的方格坐标X1,Y1,第三行为深洞所在的方格坐标X2,Y2,以下N行每行有四个数,分别是每个冰山所占的格子左上角和右下角坐标Xi1,Yi1,Xi2,Yi2
输出格式
输出文件仅包含一个整数,为最少推动冰块的次数。如果无法将冰块推入深洞中,则输出0。==================================================================
这题的几个题解都说是离散化+宽搜,但我总觉的开一个8000*8000的数组不靠谱(64M啊!)。
我的做法:
这题如果把当中可以停的点当作节点,构图,求个最短路就行了。关键是无法对点进行有效的编号,于是我想到了splay,通过一个query(x,y)函数返回对应点的指针(若该点不在容器中会自动生成一个新的点,把它的dis设成+Inf),这样在spfa的队列中只记下对应点的指针就可以了;刚开始的时候,spfa写成了栈式,tle了,对于这个有特殊性的图来说,栈式是速度最慢的,因为边权都是1,破坏了宽搜的那种最优性,如果写成队列式,搜到终点就可以exit了;由于不好确定队列开多大,我队列写成了链表;还有就是判断停止,我这题用朴素就可以过了,我用二分缩短枚举范围,但效率没高多少,应该还可以用线段树优化,但感觉没想透,所以暂时没用,在跟它类似的APIO-path里加上线段树吧~
================================================
Code:
type
link=^node;
node=record pre:link; ch:array[0..1] of link; x,y,dis:longint; end;
qlink=^qnode;
qnode=record x:link; next:qlink; end;
data=record x,low,high:longint; end;
arr=array[1..4000] of data;
var que,last:qlink;
root:link;
n,x1,y1,x2,y2:longint;
//============================================================================//
arr1,arr2,arr3,arr4:arr;
procedure insert(var a:arr;i,x,low,high:longint);
begin
a[i].x:=x;
a[i].low:=low;
a[i].high:=high;
end;
procedure sort(var a:arr;l,r:longint);
var i,j:longint; mid,tmp:data;
begin
i:=l; j:=r; mid:=a[(l+r)shr 1];
repeat
while (a[i].x<mid.x)do inc(i);
while (a[j].x>mid.x)do dec(j);
if i<=j then begin
tmp:=a[i]; a[i]:=a[j]; a[j]:=tmp;
inc(i); dec(j);
end;
until i>j;
if i<r then sort(a,i,r);
if l<j then sort(a,l,j);
end;
function up(x,y:longint;var tx:longint):boolean;{arr1}
var l,r,i,mid:longint;
begin
l:=1; r:=n;
while l<r do begin
mid:=(l+r)shr 1+1;
if arr1[mid].x<x then l:=mid
else r:=mid-1;
end;
tx:=-maxlongint;
for i:=l downto 1 do
if (arr1[i].x<x)and(arr1[i].low<=y)and(arr1[i].high>=y)then begin
tx:=arr1[i].x+1;
break;
end;
if (y=y2)and(x2>=tx)and(x2<=x)then tx:=x2;
if (tx=-maxlongint)or(tx=x)then exit(false) else exit(true);
end;
function down(x,y:longint;var tx:longint):boolean;{arr2}
var l,r,i,mid:longint;
begin
l:=1; r:=n;
while l<r do begin
mid:=(l+r)shr 1;
if arr2[mid].x>x then r:=mid
else l:=mid+1;
end;
tx:=maxlongint;
for i:=r to n do
if (arr2[i].x>x)and(arr2[i].low<=y)and(arr2[i].high>=y)then begin
tx:=arr2[i].x-1;
break;
end;
if (y=y2)and(x2<=tx)and(x2>=x)then tx:=x2;
if (tx=maxlongint)or(tx=x)then exit(false) else exit(true);
end;
function left(x,y:longint;var ty:longint):boolean;{arr4}
var l,r,i,mid:longint;
begin
l:=1; r:=n;
while l<r do begin
mid:=(l+r)shr 1+1;
if arr4[mid].x<y then l:=mid
else r:=mid-1;
end;
ty:=-maxlongint;
for i:=l downto 1 do
if (arr4[i].x<y)and(arr4[i].low<=x)and(arr4[i].high>=x)then begin
ty:=arr4[i].x+1;
break;
end;
if (x=x2)and(y2>=ty)and(y2<=y) then ty:=y2;
if (ty=-maxlongint)or(ty=y)then exit(false) else exit(true);
end;
function right(x,y:longint;var ty:longint):boolean;{arr3}
var l,r,i,mid:longint;
begin
l:=1; r:=n;
while l<r do begin
mid:=(l+r)shr 1;
if arr3[mid].x>y then r:=mid
else l:=mid+1;
end;
ty:=maxlongint;
for i:=r to n do
if (arr3[i].x>y)and(arr3[i].low<=x)and(arr3[i].high>=x)then begin
ty:=arr3[i].x-1;
break;
end;
if (x=x2)and(y2>=y)and(y2<=ty)then ty:=y2;
if (ty=maxlongint)or(ty=y)then exit(false)else exit(true);
end;
//============================================================================//
procedure rotate(x:link;k:longint);
var f:link;
begin
f:=x^.pre;
f^.ch[1-k]:=x^.ch[k]; if x^.ch[k]<>nil then x^.ch[k]^.pre:=f;
x^.pre:=f^.pre; if f^.pre<>nil then if f^.pre^.ch[0]=f then f^.pre^.ch[0]:=x else f^.pre^.ch[1]:=x;
x^.ch[k]:=f; f^.pre:=x; if f=root then root:=x;
end;
procedure splay(x,goal:link);
var y,z:link;
begin
while x^.pre<>goal do
if x^.pre^.pre=goal then
if x^.pre^.ch[0]=x then rotate(x,1)
else rotate(x,0)
else begin
y:=x^.pre; z:=y^.pre;
if z^.ch[0]=y then
if y^.ch[0]=x then begin rotate(y,1); rotate(x,1); end
else begin rotate(x,0); rotate(x,1); end
else if y^.ch[1]=x then begin rotate(y,0); rotate(x,0); end
else begin rotate(x,1); rotate(x,0); end;
end;
end;
function query(x,y:longint):link;
procedure search(var r:link);
begin
if r=nil then begin
new(r);
r^.x:=x;
r^.y:=y;
r^.dis:=maxlongint;
r^.ch[0]:=nil;
r^.ch[1]:=nil;
query:=r;
end else if r^.x<x then begin search(r^.ch[1]); r^.ch[1]^.pre:=r; end
else if r^.x>x then begin search(r^.ch[0]); r^.ch[0]^.pre:=r; end
else if r^.y<y then begin search(r^.ch[1]); r^.ch[1]^.pre:=r; end
else if r^.y>y then begin search(r^.ch[0]); r^.ch[0]^.pre:=r; end
else query:=r;
end;
begin
search(root);
root^.pre:=nil;
splay(query,nil);
end;
//============================================================================//
procedure push(x:link);
var p:qlink;
begin
new(p);
p^.x:=x;
p^.next:=nil;
if que=nil then begin
que:=p;
last:=p;
end else begin
last^.next:=p;
last:=p;
end;
end;
function pop:link;
begin
pop:=que^.x;
que:=que^.next;
end;
//============================================================================//
function spfa:longint;
var t:longint; p,q:link;
begin
que:=nil;
root:=nil;
q:=query(x1,y1);
q^.dis:=0;
push(q);
while que<>nil do begin
q:=pop;
with q^ do begin
if (x=x2)and(y=y2)then exit(dis);
if up(x,y,t) then begin
p:=query(t,y);
if p^.dis>dis+1 then begin
p^.dis:=dis+1;
push(p);
end;
end;
if down(x,y,t) then begin
p:=query(t,y);
if p^.dis>dis+1 then begin
p^.dis:=dis+1;
push(p);
end;
end;
if left(x,y,t) then begin
p:=query(x,t);
if p^.dis>dis+1 then begin
p^.dis:=dis+1;
push(p);
end;
end;
if right(x,y,t) then begin
p:=query(x,t);
if p^.dis>dis+1 then begin
p^.dis:=dis+1;
push(p);
end;
end;
end;
end;
q:=query(x2,y2);
if q^.dis=maxlongint then exit(0)
else exit(q^.dis);
end;
//
procedure main;
var i,tx1,tx2,ty1,ty2:longint;
begin
readln(n);
readln(x1,y1);
readln(x2,y2);
for i:=1 to n do begin
readln(tx1,ty1,tx2,ty2);
insert(arr1,i,tx2,ty1,ty2);
insert(arr2,i,tx1,ty1,ty2);
insert(arr3,i,ty1,tx1,tx2);
insert(arr4,i,ty2,tx1,tx2);
end;
sort(arr1,1,n);
sort(arr2,1,n);
sort(arr3,1,n);
sort(arr4,1,n);
write(spfa);
end;
begin
main;
end.