[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

这是一道神题,因为最优情况下只会在矩形的顶点处改变方向,所以可以先将坐标离散化,然后对于矩形的每一个顶点向第一个能到达的地方连边 
这样的话除了矩形的顶点图上还会多出来一些有效的点,对于所有的有效点向其四个方向最近的点连边,然后跑最短路就行了

 #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");
}
}

bzoj 2304 [Apio2011]寻路 Dij+模拟+恶心建图的更多相关文章

  1. bzoj 2304: [Apio2011]寻路【spfa】

    我是智障*3,读优写错了调了半天没发现= = 虽然是个最短路却有网络流一般的神建图啊. 首先发现在拐角处转弯是最优的,于是先离散化,然后矩形的四个顶点向距离它最近的上下左右点连边,跑spfa即可. 就 ...

  2. BZOJ 1924 && Luogu P2403 [SDOI2010]所驼门王的宝藏 恶心建图+缩点DP

    记住:map一定要这么用: if(mp[x[i]+dx[j]].find(y[i]+dy[j])!=mp[x[i]+dx[j]].end()) add(i,mp[x[i]+dx[j]][y[i]+dy ...

  3. HDU 4522 (恶心建图)

    湫湫系列故事——过年回家 Time Limit: 500/200 MS (Java/Others)    Memory Limit: 65535/32768 K (Java/Others)Total ...

  4. bzoj 4070 [Apio2015]雅加达的摩天楼 Dijkstra+建图

    [Apio2015]雅加达的摩天楼 Time Limit: 10 Sec  Memory Limit: 256 MBSubmit: 644  Solved: 238[Submit][Status][D ...

  5. BZOJ.3495.[PA2010]Riddle(2-SAT 前缀优化建图)

    题目链接 每个城市要么建首都要么不建,考虑2-SAT 这样一个国家内城市两两连边是很显然的,但是边数为O(n^2) 每个国家中仅有一个建首都,考虑新建前缀S[i]=1/0这2n个点表示当前国家的[1, ...

  6. poj1122 FDNY to the Rescue!(dij+反向建图+输出路径)

    题目链接:poj1122 FDNY to the Rescue! 题意:给出矩阵,矩阵中每个元素tij表示从第i个交叉路口到第j个交叉路口所需时间,若tij为-1则表示两交叉路口之间没有直接路径,再给 ...

  7. BZOJ.3218.a + b Problem(最小割ISAP 可持久化线段树优化建图)

    BZOJ UOJ 首先不考虑奇怪方格的限制,就是类似最大权闭合子图一样建图. 对于奇怪方格的影响,显然可以建一条边\((i\to x,p_i)\),然后由\(x\)向\(1\sim i-1\)中权值在 ...

  8. Leapin' Lizards HDU - 2732 (恶心的建图。。)

    这道题其实不难...就是建图恶心了点....emm... 题意: 多源多汇 + 拆边 青蛙跳柱子, 每根柱子都有一定的承载能力, 青蛙跳上去之后柱子的承载能力就会减一,跳到边界就能活 跳不到就over ...

  9. BZOJ 4289: PA2012 Tax 差分建图 最短路

    https://www.lydsy.com/JudgeOnline/problem.php?id=4289 https://www.cnblogs.com/clrs97/p/5046933.html  ...

随机推荐

  1. windows程序内部运行机制

    Windows程序内部运行机制 2007-10-21 19:52 1010人阅读 评论(0) 收藏 举报 windowsvc++applicationcallbackwinapistructure W ...

  2. 004---Python基本数据类型--元祖

    元祖 .caret, .dropup > .btn > .caret { border-top-color: #000 !important; } .label { border: 1px ...

  3. (数据科学学习手札14)Mean-Shift聚类法简单介绍及Python实现

    不管之前介绍的K-means还是K-medoids聚类,都得事先确定聚类簇的个数,而且肘部法则也并不是万能的,总会遇到难以抉择的情况,而本篇将要介绍的Mean-Shift聚类法就可以自动确定k的个数, ...

  4. MySQL共享表空间扩容

    一.什么是共享表空间和独占表空间 共享表空间以及独占表空间都是针对数据的存储方式而言的. 共享表空间: 某一个数据库的所有的表数据,索引文件全部放在一个文件中,默认这个共享表空间的文件路径在data目 ...

  5. 20160120使用myeclipse一年开始转IntelliJ IDEA 15做以下总结

    20160120使用myeclipse一年开始费元星转IntelliJ IDEA 15做以下总结 1.输入psv就会看到一个psvm的提示,此时点击tab键一个main方法就写好了.psvm 也就是p ...

  6. Linux-Shell脚本编程-学习-1-Linux基本命令

    在学习Linux-Shell脚本编程之前,我们需要学习一定的Linux基本命令,不然在后面学习Shell脚本编程的的时候,我们就呵呵了. 我学习所用的系统是Ubuntu 16.04版本 也没有什么规则 ...

  7. 前端----css总结

    1,权重计算: 权重:id  class  标签--->>>顺序不变 当权重一样时,显示后来设置的 继承下来的标签,权重为0 若权重为0,那么谁描述的近,就显示谁 若权重为0,描述的 ...

  8. LAXCUS对数据存储的优化

        LAXCUS兼容行存储(NSM)和列存储(DSM)两种数据模型,实现了混合存储.同时在分布环境里,做到将数据的分发和备份自动处理,这样就不再需要人工干预了.     行存储,为了兼容广大用户对 ...

  9. Web负载均衡技术

    Web负载均衡(Load Balancing),简单地说就是给我们的服务器集群分配“工作任务”,而采用恰当的分配方式,对于保护处于后端的Web服务器来说,非常重要. 负载均衡的策略有很多,我们从简单的 ...

  10. LeetCode 19——删除链表的倒数第 N 个节点

    1. 题目 给定一个链表,删除链表的倒数第 n 个节点,并且返回链表的头结点. 示例: 给定一个链表: 1->2->3->4->5, 和 n = 2. 当删除了倒数第二个节点后 ...