[Apio2011]寻路
Time Limit: 20 Sec Memory Limit: 256 MB
Submit: 624 Solved: 193
[Submit][Status][Discuss]
Description
TooDee是一块二维格子状的土地(就像著名的笛卡尔坐标系那样) ,在这里
生活着很多可爱的Dee。Dee是像蜜蜂一样的小动物,它们只在二维活动,而且
它们非常的文明开化。TooDee 的蜂窝和正常世界的蜂窝也是很不一样的,它们
是矩形的且它们的边平行于TooDee的地理坐标系,就是说矩形的边或者是东西
走向,或者是南北走向。
因为 Dees 是很高级的生物,它们有很多固定的飞行轨道,这些轨道由一些
平行于坐标轴的线段组成,线段只会在经纬度都是整数的点相交。 Dee在TooDee
飞行时必须遵守以下规则(请记住TooDee中所有点的经纬度都是整数):
1 如果当前在点(XS, YS), 则下步只能飞到四个邻点 (XS, YS – 1), (XS, YS + 1),
(XS – 1, YS ), (XS + 1, YS );
2 不可以进入蜂巢;
3 只能在蜂巢的角或者边上改变飞行方向;
4 开始的时候可以向任何方向飞;
今晚是公共财政大臣Deeficer的女儿的生日,她想尽早回家,请帮她找到最
快的回家路径。假设她每秒可以飞行一个单位的距离。
Input
每个测试点包含多组数据。
输入的第一行包含一个整数T,表示测试数据的组数。接下来依次描述这T
组数据,相邻的两组之间使用一个空行分隔。测试数据不多于20组。
对于每组数据,第一行包含4个整数 xs, ys, xt, yt,表示Deeficer 的办公室和
家的坐标分别为(xs, ys)和(xt, yt)。第二行包含一个整数n,表示蜂巢的个数。接下
来的n行描述所有的蜂巢,其中第 i行包含 4 个整数xi1, yi1, xi2, yi2,表示第i个
蜂巢两个对角的坐标分别为(xi1, yi1)和(xi2, yi2)。
任何两个蜂巢都不会相交,也不会接触(在角上也不会接触)。办公室和家
处在不同的位置。每个蜂巢的面积为正。
Output
对于每一组数据,输出一个整数,表示Deeficer 最快回家的时间(单位为秒),
如果她无法按规则回家,则输出“No Path”。
对于100%的测试数据,1 ≤ n ≤ 1000,所有坐标都是不超过10^9
的整数;
Sample Input
1 7 7 8
2
2 5 3 8
4 10 6 7
2 1 5 4
1
3 1 4 3
Sample Output
No Path
HINT
这是一道神题,因为最优情况下只会在矩形的顶点处改变方向,所以可以先将坐标离散化,然后对于矩形的每一个顶点向第一个能到达的地方连边
这样的话除了矩形的顶点图上还会多出来一些有效的点,对于所有的有效点向其四个方向最近的点连边,然后跑最短路就行了
#include<cstring>
#include<cmath>
#include<iostream>
#include<algorithm>
#include<cstdio>
#include<set>
#include<queue> #define ll long long
#define inf 2000000000
#define llinf 8000000000000000000LL
#define pa pair<ll,int>
using namespace std;
inline int read()
{
int x=,f=;char ch=getchar();
while(!isdigit(ch)){if(ch=='-')f=-;ch=getchar();}
while(isdigit(ch)){x=(x<<)+(x<<)+ch-'';ch=getchar();}
return x*f;
}
int xs,ys,xt,yt,st,ed;
int n,s,T,cnt,sz;
int mark[][],sx[],sy[];
int x1[],ya[],x2[],y2[],d[][],last[];
bool vis[];
ll dis[];
set <int> x[],y[];
struct edge{int to,next,v;}e[];
struct ed1{int ya,y2,x;}a[];
struct ed2{int x1,x2,y;}b[];
struct seg{int l,r,tag,v;}t[]; inline bool cp1(ed1 a,ed1 b){return a.x<b.x;}
inline bool cp2(ed1 a,ed1 b){return a.x>b.x;}
inline bool cp3(ed2 a,ed2 b){return a.y<b.y;}
inline bool cp4(ed2 a,ed2 b){return a.y>b.y;}
void insert(int u,int v,int w)
{
e[++cnt].to=v;e[cnt].next=last[u];last[u]=cnt;e[cnt].v=w;
e[++cnt].to=u;e[cnt].next=last[v];last[v]=cnt;e[cnt].v=w;
}
int find(bool f,int x)
{
int l=,r=*n+;
while(l<=r)
{
int mid=(l+r)>>;
if(d[f][mid]==x) return mid;
else if(d[f][mid]<x)l=mid+;
else r=mid-;
}
}
void build(int k,int l,int r)
{
t[k].l=l;t[k].r=r;t[k].v=t[k].tag=;
if(l==r)return;
int mid=(l+r)>>;
build(k<<,l,mid);build(k<<|,mid+,r);
}
void pushdown(int k)
{
if(t[k].l==t[k].r||!t[k].tag)return;
int tag=t[k].tag;t[k].tag=;
t[k<<].tag=t[k<<].v=tag;
t[k<<|].tag=t[k<<|].v=tag;
}
void modify(int k,int x,int y,int val)
{
pushdown(k);int l=t[k].l,r=t[k].r;
if(l==x&&y==r){t[k].tag=t[k].v=val;return;}
int mid=(l+r)>>;
if(y<=mid)modify(k<<,x,y,val);
else if(x>mid)modify(k<<|,x,y,val);
else modify(k<<,x,mid,val),modify(k<<|,mid+,y,val);
}
int query(int k,int x)
{
pushdown(k);int l=t[k].l,r=t[k].r;
if(l==r)return t[k].v;
int mid=(l+r)>>;
if(x<=mid)return query(k<<,x);
else return query(k<<|,x);
}
inline int get(int a,int b)
{
if(mark[a][b])return mark[a][b];
sz++;mark[a][b]=sz;
sx[sz]=a;sy[sz]=b;
return sz;
}
void add(int x1,int ya,int x2,int y2)
{
if(x1==x2&&ya==y2)return;
int t1=get(x1,ya),t2=get(x2,y2);
insert(t1,t2,abs(d[][x1]-d[][x2]+d[][ya]-d[][y2]));
}
inline void spreadx(int a,int b)
{
int r=*y[b].lower_bound(a);if(r==a)return;
int l=*--y[b].lower_bound(a);
if(l!=-inf)add(a,b,l,b);if(r!=inf)add(a,b,r,b);
}
inline void spready(int a,int b)
{
int r=*x[a].lower_bound(b);if(r==b)return;
int l=*--x[a].lower_bound(b);
if(l!=-inf)add(a,b,a,l);if(r!=inf)add(a,b,a,r);
}
inline void put(int a,int b)
{
x[a].insert(b);y[b].insert(a);
}
void solve(int a,int b,bool f)
{
int mx=,mn=inf;
if(!f&&xs==xt){if(yt>ys)mn=yt;else mx=yt;}
for(int i=;i<=n;i++)
{
if(x1[i]>a||x2[i]<a)continue;
if(ya[i]>=b)mn=min(ya[i],mn);
if(y2[i]<=b)mx=max(y2[i],mx);
}
if(mx)add(a,b,a,mx),spreadx(a,mx),put(a,mx);
if(mn!=inf)add(a,b,a,mn),spreadx(a,mn),put(a,mn);
mx=,mn=inf;
if(!f&&ys==yt){if(xt>xs)mn=xt;else mx=xt;}
for(int i=;i<=n;i++)
{
if(ya[i]>b||y2[i]<b)continue;
if(x1[i]>=a)mn=min(x1[i],mn);
if(x2[i]<=a)mx=max(x2[i],mx);
}
if(mx)add(a,b,mx,b),spready(mx,b),put(mx,b);
if(mn!=inf)add(a,b,mn,b),spready(mn,b),put(mn,b);
}
void sol1()
{
build(,,*n+);
for(int i=;i<=s;i++)
{
int ya=a[i].ya,y2=a[i].y2,x=a[i].x;
int t1=query(,ya),t2=query(,y2);
if(t1)add(x,ya,t1,ya),spready(t1,ya),put(t1,ya);
if(t2)add(x,y2,t2,y2),spready(t2,y2),put(t2,y2);
modify(,ya,y2,x);
}
}
void sol2()
{
build(,,*n+);
for(int i=;i<=s;i++)
{
int x1=b[i].x1,x2=b[i].x2,y=b[i].y;
int t1=query(,x1),t2=query(,x2);
if(t1)add(x1,y,x1,t1),spreadx(x1,t1),put(x1,t1);
if(t2)add(x2,y,x2,t2),spreadx(x2,t2),put(x2,t2);
modify(,x1,x2,y);
}
}
void buildmap()
{
sort(a+,a+s+,cp1);sol1();sort(a+,a+s+,cp2);sol1();
sort(b+,b+s+,cp3);sol2();sort(b+,b+s+,cp4);sol2();
}
void dijkstra()
{
priority_queue<pa,vector<pa>,greater<pa> > q;
for(int i=;i<=sz;i++)dis[i]=llinf;
dis[st]=;q.push(make_pair(,st));
while(!q.empty())
{
int now=q.top().second;q.pop();
if(vis[now])continue;vis[now]=;
for(int i=last[now];i;i=e[i].next)
if(dis[now]+e[i].v<dis[e[i].to])
{
dis[e[i].to]=dis[now]+e[i].v;
q.push(make_pair(dis[e[i].to],e[i].to));
}
}
}
int main()
{
T=read();
while(T--)
{
for(int i=;i<=sz;i++)mark[sx[i]][sy[i]]=vis[i]=last[i]=;
cnt=sz=s=;
xs=read();ys=read();xt=read();yt=read();n=read();
for(int i=;i<=*n+;i++)
{
x[i].clear();x[i].insert(inf);x[i].insert(-inf);
y[i].clear();y[i].insert(inf);y[i].insert(-inf);
}
for(int i=;i<=n;i++)
{
x1[i]=d[][*i-]=read();ya[i]=d[][*i-]=read();
x2[i]=d[][*i]=read();y2[i]=d[][*i]=read();
if(x1[i]>x2[i])swap(x1[i],x2[i]);
if(ya[i]>y2[i])swap(ya[i],y2[i]);
}
d[][*n+]=xs;d[][*n+]=xt;d[][*n+]=ys;d[][*n+]=yt;
sort(d[]+,d[]+*n+);sort(d[]+,d[]+*n+);
for(int i=;i<=n;i++)
{
x1[i]=find(,x1[i]),x2[i]=find(,x2[i]);
ya[i]=find(,ya[i]),y2[i]=find(,y2[i]);
++s;
b[s].y=ya[i];b[s].x1=x1[i];b[s].x2=x2[i];
a[s].x=x1[i];a[s].ya=ya[i];a[s].y2=y2[i];
++s;
b[s].y=y2[i];b[s].x1=x1[i];b[s].x2=x2[i];
a[s].x=x2[i];a[s].ya=ya[i];a[s].y2=y2[i];
put(x1[i],ya[i]);put(x2[i],y2[i]);
put(x1[i],y2[i]);put(x2[i],ya[i]);
}
buildmap();
xs=find(,xs);xt=find(,xt);ys=find(,ys);yt=find(,yt);
solve(xs,ys,);solve(xt,yt,);
st=mark[xs][ys];ed=mark[xt][yt];
if(!st||!ed){puts("No Path");continue;}
dijkstra();
if(dis[ed]!=llinf)printf("%lld\n",dis[ed]);
else puts("No Path");
}
}