zoukankan      html  css  js  c++  java
  • bzoj 2304 [Apio2011]寻路 Dij+模拟+恶心建图

    [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

    2

    1 7 7 8
    2
    2 5 3 8
    4 10 6 7

    2 1 5 4
    1
    3 1 4 3

    Sample Output

    9
    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 }
  • 相关阅读:
    镜像转换:img转换为iso
    IDM的谷歌插件安装
    Adams和UG许可证冲突问题
    步进电机驱动总结
    比赛官网收集
    树莓派安装pip包管理工具
    光固化打印后处理过程
    Arduino 串口库函数
    六足蜘蛛机器人行走控制
    温湿度传感器DHT11程序示例
  • 原文地址:https://www.cnblogs.com/fengzhiyuan/p/8745610.html
Copyright © 2011-2022 走看看