[Apio2011]寻路
Time Limit: 20 Sec Memory Limit: 256 MBSubmit: 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
这是一道神题,因为最优情况下只会在矩形的顶点处改变方向,所以可以先将坐标离散化,然后对于矩形的每一个顶点向第一个能到达的地方连边
这样的话除了矩形的顶点图上还会多出来一些有效的点,对于所有的有效点向其四个方向最近的点连边,然后跑最短路就行了
1 #include<cstring> 2 #include<cmath> 3 #include<iostream> 4 #include<algorithm> 5 #include<cstdio> 6 #include<set> 7 #include<queue> 8 9 #define ll long long 10 #define inf 2000000000 11 #define llinf 8000000000000000000LL 12 #define pa pair<ll,int> 13 using namespace std; 14 inline int read() 15 { 16 int x=0,f=1;char ch=getchar(); 17 while(!isdigit(ch)){if(ch=='-')f=-1;ch=getchar();} 18 while(isdigit(ch)){x=(x<<1)+(x<<3)+ch-'0';ch=getchar();} 19 return x*f; 20 } 21 int xs,ys,xt,yt,st,ed; 22 int n,s,T,cnt,sz; 23 int mark[2005][2005],sx[20005],sy[20005]; 24 int x1[1005],ya[1005],x2[1005],y2[1005],d[2][2005],last[20005]; 25 bool vis[20005]; 26 ll dis[20005]; 27 set <int> x[2005],y[2005]; 28 struct edge{int to,next,v;}e[500005]; 29 struct ed1{int ya,y2,x;}a[2005]; 30 struct ed2{int x1,x2,y;}b[2005]; 31 struct seg{int l,r,tag,v;}t[8005]; 32 33 inline bool cp1(ed1 a,ed1 b){return a.x<b.x;} 34 inline bool cp2(ed1 a,ed1 b){return a.x>b.x;} 35 inline bool cp3(ed2 a,ed2 b){return a.y<b.y;} 36 inline bool cp4(ed2 a,ed2 b){return a.y>b.y;} 37 void insert(int u,int v,int w) 38 { 39 e[++cnt].to=v;e[cnt].next=last[u];last[u]=cnt;e[cnt].v=w; 40 e[++cnt].to=u;e[cnt].next=last[v];last[v]=cnt;e[cnt].v=w; 41 } 42 int find(bool f,int x) 43 { 44 int l=1,r=2*n+2; 45 while(l<=r) 46 { 47 int mid=(l+r)>>1; 48 if(d[f][mid]==x) return mid; 49 else if(d[f][mid]<x)l=mid+1; 50 else r=mid-1; 51 } 52 } 53 void build(int k,int l,int r) 54 { 55 t[k].l=l;t[k].r=r;t[k].v=t[k].tag=0; 56 if(l==r)return; 57 int mid=(l+r)>>1; 58 build(k<<1,l,mid);build(k<<1|1,mid+1,r); 59 } 60 void pushdown(int k) 61 { 62 if(t[k].l==t[k].r||!t[k].tag)return; 63 int tag=t[k].tag;t[k].tag=0; 64 t[k<<1].tag=t[k<<1].v=tag; 65 t[k<<1|1].tag=t[k<<1|1].v=tag; 66 } 67 void modify(int k,int x,int y,int val) 68 { 69 pushdown(k);int l=t[k].l,r=t[k].r; 70 if(l==x&&y==r){t[k].tag=t[k].v=val;return;} 71 int mid=(l+r)>>1; 72 if(y<=mid)modify(k<<1,x,y,val); 73 else if(x>mid)modify(k<<1|1,x,y,val); 74 else modify(k<<1,x,mid,val),modify(k<<1|1,mid+1,y,val); 75 } 76 int query(int k,int x) 77 { 78 pushdown(k);int l=t[k].l,r=t[k].r; 79 if(l==r)return t[k].v; 80 int mid=(l+r)>>1; 81 if(x<=mid)return query(k<<1,x); 82 else return query(k<<1|1,x); 83 } 84 inline int get(int a,int b) 85 { 86 if(mark[a][b])return mark[a][b]; 87 sz++;mark[a][b]=sz; 88 sx[sz]=a;sy[sz]=b; 89 return sz; 90 } 91 void add(int x1,int ya,int x2,int y2) 92 { 93 if(x1==x2&&ya==y2)return; 94 int t1=get(x1,ya),t2=get(x2,y2); 95 insert(t1,t2,abs(d[0][x1]-d[0][x2]+d[1][ya]-d[1][y2])); 96 } 97 inline void spreadx(int a,int b) 98 { 99 int r=*y[b].lower_bound(a);if(r==a)return; 100 int l=*--y[b].lower_bound(a); 101 if(l!=-inf)add(a,b,l,b);if(r!=inf)add(a,b,r,b); 102 } 103 inline void spready(int a,int b) 104 { 105 int r=*x[a].lower_bound(b);if(r==b)return; 106 int l=*--x[a].lower_bound(b); 107 if(l!=-inf)add(a,b,a,l);if(r!=inf)add(a,b,a,r); 108 } 109 inline void put(int a,int b) 110 { 111 x[a].insert(b);y[b].insert(a); 112 } 113 void solve(int a,int b,bool f) 114 { 115 int mx=0,mn=inf; 116 if(!f&&xs==xt){if(yt>ys)mn=yt;else mx=yt;} 117 for(int i=1;i<=n;i++) 118 { 119 if(x1[i]>a||x2[i]<a)continue; 120 if(ya[i]>=b)mn=min(ya[i],mn); 121 if(y2[i]<=b)mx=max(y2[i],mx); 122 } 123 if(mx)add(a,b,a,mx),spreadx(a,mx),put(a,mx); 124 if(mn!=inf)add(a,b,a,mn),spreadx(a,mn),put(a,mn); 125 mx=0,mn=inf; 126 if(!f&&ys==yt){if(xt>xs)mn=xt;else mx=xt;} 127 for(int i=1;i<=n;i++) 128 { 129 if(ya[i]>b||y2[i]<b)continue; 130 if(x1[i]>=a)mn=min(x1[i],mn); 131 if(x2[i]<=a)mx=max(x2[i],mx); 132 } 133 if(mx)add(a,b,mx,b),spready(mx,b),put(mx,b); 134 if(mn!=inf)add(a,b,mn,b),spready(mn,b),put(mn,b); 135 } 136 void sol1() 137 { 138 build(1,1,2*n+2); 139 for(int i=1;i<=s;i++) 140 { 141 int ya=a[i].ya,y2=a[i].y2,x=a[i].x; 142 int t1=query(1,ya),t2=query(1,y2); 143 if(t1)add(x,ya,t1,ya),spready(t1,ya),put(t1,ya); 144 if(t2)add(x,y2,t2,y2),spready(t2,y2),put(t2,y2); 145 modify(1,ya,y2,x); 146 } 147 } 148 void sol2() 149 { 150 build(1,1,2*n+2); 151 for(int i=1;i<=s;i++) 152 { 153 int x1=b[i].x1,x2=b[i].x2,y=b[i].y; 154 int t1=query(1,x1),t2=query(1,x2); 155 if(t1)add(x1,y,x1,t1),spreadx(x1,t1),put(x1,t1); 156 if(t2)add(x2,y,x2,t2),spreadx(x2,t2),put(x2,t2); 157 modify(1,x1,x2,y); 158 } 159 } 160 void buildmap() 161 { 162 sort(a+1,a+s+1,cp1);sol1();sort(a+1,a+s+1,cp2);sol1(); 163 sort(b+1,b+s+1,cp3);sol2();sort(b+1,b+s+1,cp4);sol2(); 164 } 165 void dijkstra() 166 { 167 priority_queue<pa,vector<pa>,greater<pa> > q; 168 for(int i=1;i<=sz;i++)dis[i]=llinf; 169 dis[st]=0;q.push(make_pair(0,st)); 170 while(!q.empty()) 171 { 172 int now=q.top().second;q.pop(); 173 if(vis[now])continue;vis[now]=1; 174 for(int i=last[now];i;i=e[i].next) 175 if(dis[now]+e[i].v<dis[e[i].to]) 176 { 177 dis[e[i].to]=dis[now]+e[i].v; 178 q.push(make_pair(dis[e[i].to],e[i].to)); 179 } 180 } 181 } 182 int main() 183 { 184 T=read(); 185 while(T--) 186 { 187 for(int i=1;i<=sz;i++)mark[sx[i]][sy[i]]=vis[i]=last[i]=0; 188 cnt=sz=s=0; 189 xs=read();ys=read();xt=read();yt=read();n=read(); 190 for(int i=1;i<=2*n+2;i++) 191 { 192 x[i].clear();x[i].insert(inf);x[i].insert(-inf); 193 y[i].clear();y[i].insert(inf);y[i].insert(-inf); 194 } 195 for(int i=1;i<=n;i++) 196 { 197 x1[i]=d[0][2*i-1]=read();ya[i]=d[1][2*i-1]=read(); 198 x2[i]=d[0][2*i]=read();y2[i]=d[1][2*i]=read(); 199 if(x1[i]>x2[i])swap(x1[i],x2[i]); 200 if(ya[i]>y2[i])swap(ya[i],y2[i]); 201 } 202 d[0][2*n+1]=xs;d[0][2*n+2]=xt;d[1][2*n+1]=ys;d[1][2*n+2]=yt; 203 sort(d[0]+1,d[0]+2*n+3);sort(d[1]+1,d[1]+2*n+3); 204 for(int i=1;i<=n;i++) 205 { 206 x1[i]=find(0,x1[i]),x2[i]=find(0,x2[i]); 207 ya[i]=find(1,ya[i]),y2[i]=find(1,y2[i]); 208 ++s; 209 b[s].y=ya[i];b[s].x1=x1[i];b[s].x2=x2[i]; 210 a[s].x=x1[i];a[s].ya=ya[i];a[s].y2=y2[i]; 211 ++s; 212 b[s].y=y2[i];b[s].x1=x1[i];b[s].x2=x2[i]; 213 a[s].x=x2[i];a[s].ya=ya[i];a[s].y2=y2[i]; 214 put(x1[i],ya[i]);put(x2[i],y2[i]); 215 put(x1[i],y2[i]);put(x2[i],ya[i]); 216 } 217 buildmap(); 218 xs=find(0,xs);xt=find(0,xt);ys=find(1,ys);yt=find(1,yt); 219 solve(xs,ys,0);solve(xt,yt,1); 220 st=mark[xs][ys];ed=mark[xt][yt]; 221 if(!st||!ed){puts("No Path");continue;} 222 dijkstra(); 223 if(dis[ed]!=llinf)printf("%lld ",dis[ed]); 224 else puts("No Path"); 225 } 226 }