[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. Go web表单验证

    开发Web的一个原则就是,不能信任用户输入的任何信息,所以验证和过滤用户的输入信息就变得非常重要 必填字段 if len(r.Form["username"][0])==0{ // ...

  2. 分享一个工作中遇得到的sql(按每天每人统计拖车次数与小修次数)

    查询每人每天的数据 首先先建表 CREATE TABLE `user` ( `name` ) DEFAULT NULL ) ENGINE=InnoDB DEFAULT CHARSET=utf8; CR ...

  3. LOOP AT SCREEN

    用法 主に.画面の属性を変更させるために使用する. 照会モードでは入力不可とするが入力可能モードでは入力可能とする.ラジオボタンAが選択された場合はラジオボタンBに関連する項目は非表示とするなど.   ...

  4. python2.7练习小例子(十一)

        11):题目:判断101-200之间有多少个素数,并输出所有素数.     程序分析:判断素数的方法:用一个数分别去除2到sqrt(这个数),如果能被整除,则表明此数不是素数,反之是素数.   ...

  5. Git的使用规范(二)

    今天,我们来介绍一下git的一些命令行,来帮我们后面可以面对一些情况的时候,我们可以有一些解决的方法 1.git查看历史记录最全的命令行 git log --pretty=raw 2.对于一下的几个情 ...

  6. js 实现字符串转日期进行比较大小

    代码如下 var a = '2016-01-01 12:12:12'; var b = '2016-01-01 12:12:13'; var al = new Date(a).getTime(); v ...

  7. Hibernate-ORM:09.Hibernate中的getCurrentSession()

    ------------吾亦无他,唯手熟尔,谦卑若愚,好学若饥------------- 本篇博客将讲述,以优雅的方式创建session对象,我将会说明优点,并提炼成工具类 优点: 1.无需手动关闭s ...

  8. 创龙DSP6748开发板SYS/BIOS的LED闪烁-第2篇

    1. 作为1个456MHz的处理器,不跑个操作系统说不过去,直接打开工程\Demo\SYSBIOS\Application\GPIO_LED,主函数比较简单 // 创建任务 Task_create(t ...

  9. 数据库学习(四)with as (补充 nvl 和 count 函数)

    with as 的专业解释我这就不详细说明了,我这就梳理下我自己的实践应用,就是根据某个条件查询出结果集放在一个临时表里面,可以创建多个临时表,然后再从这些临时表中查询出要的数据. 参考资料:http ...

  10. js中DOM 节点的一些操作方法

    什么是DOM DOM:文档对象模型.DOM 为文档提供了结构化表示,并定义了如何通过脚本来访问文档结构.目的其实就是为了能让js操作html元素而制定的一个规范. DOM就是由节点组成的. 解析过程 ...