![](http://acm.fzu.edu.cn/image/problem.gif)
Accept: 49 Submit: 260
Time Limit: 1000 mSec Memory Limit : 32768 KB
Problem Description
黑暗之王有一片棋盘般的疆土,这片疆土有2*10^9行,有2*10^9列。假设这块疆土的行从上到下编号1到2*10^9,它的列从左到右也编号1到2*10^9。我们可以把第i行第j列的方格记为坐标(i,j)。
但是这偌大棋盘只有被给的N个线状区域才是允许通行的。每个线状区域被三个参数描述,ri,ai,bi(ai<= bi)。ri代表给定线状区域的行编号,ai代表线状区域的起始列编号,bi代表末尾编号。
现在国王想要从一个给定坐标方格(x0,y0)通过最小移动步数到达终点坐标方格(x1,y1),而且只能通过上述给出的允许通行的线状区域。
国王移动一步只能发生在相邻的方格之间。此外,如果两个方格至少共享一个点我们便认为他们相邻。
Input
有多组数据(<=30),处理到文件尾(EOF)。
每组数据第一行包含四个整数,x0, y0, x1, y1(1 <= x0, y0, x1, y1 <= 2*10^9),分别代表国王的初始坐标和终点坐标。
第二行有一个整数N (1 <= N <= 10^5),代表有N条可通行的线状区域。
接下里会有N行,第i行包含三个整数,ri,ai, bi (1 <= ri, ai bi <= 2*10^9),含义看题面。
数据允许线状区域会有交叉或者嵌套。
数据保证国王的起点方格和终点方格都是可通行的,并且两个区域不相同。另外保证所有线状区域的的长度总和不超过10^5。
1 <= x0, y0, x1, y1, ri, ai, bi<= 2*10^9,1 <= N <= 10^5
Output
如果没有一条道路使得国王从起始区域到达终点区域,则输出 -1。
否则,则输出国王的从起始区域到达终点区域的最小步数。
Sample Input
Sample Output
Source
福州大学第十三届程序设计竞赛
思路(思路代码参考自:http://blog.csdn.net/tc_to_top/article/details/51567161):
就是考验代码能力的一道题。
然而直接Map+排序,分成行和列去离散化的话,FZU没有开O2加速,Map会一直TLE...............................
所以我们不妨换个思路。
我们用pair存入所有点,因为点的个数不超过1e5.所以我们对线段所覆盖的点去重并存入即可。
然后我们直接将每个点拿出,看看其周围8个位子是否能走,如果有能走的地方,直接建一条边就行。
然后跑一下Bfs就行了。
Ac代码:
/*
代码参考自:http://blog.csdn.net/tc_to_top/article/details/51567161
*/
#include<stdio.h>
#include<string.h>
#include<algorithm>
#include<queue>
using namespace std;
struct node
{
int from;
int to;
int next;
}e[105000*8];
int cont;
int head[105000];
int dist[105000];
int fx[8]={0,0,1,-1,-1,1,-1,1};
int fy[8]={1,-1,0,0,-1,1,1,-1};
pair<int ,int >p[105000];
int cnt;
int sx,sy,ex,ey;
void add(int from,int to)
{
e[cont].to=to;
e[cont].next=head[from];
head[from]=cont++;
}
void SPFA()
{
for(int i=1;i<=cnt;i++)dist[i]=0x3f3f3f3f;
int ss=lower_bound(p+1,p+1+cnt,make_pair(sx,sy))-p;
int tt=lower_bound(p+1,p+1+cnt,make_pair(ex,ey))-p;
dist[ss]=0;
queue<int>s;
s.push(ss);
while(!s.empty())
{
int u=s.front();
s.pop();
for(int i=head[u];i!=-1;i=e[i].next)
{
int v=e[i].to;
if(dist[v]>dist[u]+1)
{
dist[v]=dist[u]+1;
s.push(v);
}
}
}
if(dist[tt]==0x3f3f3f3f)printf("-1\n");
else printf("%d\n",dist[tt]);
}
int main()
{
while(~scanf("%d%d%d%d",&sx,&sy,&ex,&ey))
{
cnt=0;
cont=0;
int tot;
scanf("%d",&tot);
memset(head,-1,sizeof(head));
for(int i=0;i<tot;i++)
{
int h,l,r;
scanf("%d%d%d",&h,&l,&r);
for(int j=l;j<=r;j++)
{
p[++cnt]=make_pair(h,j);
}
}
sort(p+1,p+cnt+1);
cnt=unique(p+1,p+cnt+1)-p-1;
for(int i=1;i<=cnt;i++)
{
for(int j=0;j<8;j++)
{
pair<int ,int >now=make_pair(p[i].first+fx[j],p[i].second+fy[j]);
int pos=lower_bound(p+1,p+cnt+1,now)-p;
if(p[pos].first==p[i].first+fx[j]&&p[pos].second==p[i].second+fy[j])
{
add(i,pos);
}
}
}
SPFA();
}
}