描述
尼莫是一个顽皮的男孩。有一天,他独自进入了深海。不幸的是,他迷路了,找不到回家的路。因此,他向他父亲马林发出了一个信号,要求他帮忙。
检查地图后,马林发现大海就像一个有墙壁和门的迷宫。所有壁都平行于X轴或Y轴。假设壁的厚度为零。
所有的门都在墙上打开,长度为1.除非墙上有门,否则马林不能通过墙。因为通过一扇门是危险的(门附近可能有一些恶毒的medusas),Marlin想要通过尽可能少的门来找到Nemo。
图1显示了迷宫的一个例子以及Marlin找到Nemo的路径。
我们假设Marlin的初始位置是(0,0)。鉴于Nemo的位置以及墙壁和门的配置,请编写一个程序来计算Marlin为达到Nemo而必须经过的最小门数。
输入
输入包含几个测试用例。每个测试用例由两个非负整数M和N开始.M表示迷宫中的墙数,N表示门的数量。
然后跟随M行,每行包含四个以下列格式描述墙的整数:
xydt
(x,y)表示墙的左下角,d是墙的方向 - 0表示它与X平行-axis和1表示它与Y轴平行,t表示墙的长度。
任何墙的两端坐标将在[1,199]范围内。
然后有N行描述门:
xyd
x,y,d与墙具有相同的含义。由于门的固定长度为1,因此省略了t。
每个案例的最后一行包含两个正浮点数:
f1 f2
(f1,f2)给出了Nemo的位置。它不会位于任何墙壁或门内。
M = -1且N = -1的测试用例表示输入结束,不应进行处理。
产量
对于每个测试用例,请在单独的一行中输出Marlin必须经过的最小门数才能营救他的儿子。如果他不能到达Nemo,输出-1。
Sample Input
8 9 1 1 1 3 2 1 1 3 3 1 1 3 4 1 1 3 1 1 0 3 1 2 0 3 1 3 0 3 1 4 0 3 2 1 1 2 2 1 2 3 1 3 1 1 3 2 1 3 3 1 1 2 0 3 3 0 4 3 1 1.5 1.5 4 0 1 1 0 1 1 1 1 1 2 1 1 1 1 2 0 1 1.5 1.7 -1 -1
Sample Output
5 -1
建图方法有点麻烦,把墙和门设作坐标点的属性,
循环队列进行广搜,每次循环四个方向
#include <iostream>
#include <cstdio>
#include <cstring>
#include <stdlib.h>
#include <algorithm>
#include <queue>
#define N 201
#define inf 0x3f3f3f3f
using namespace std;
struct node
{
int step; //记录穿过的门数
int f[4]; //0,1,2,3 表示上下左右四个边
} a[N][N];
bool v[N][N];
int xx[]= {0,0,-1,1}; //上下左右
int yy[]= {1,-1,0,0};
void bfs(int x,int y)
{
queue<pair<int,int> >q;
q.push(pair<int ,int >(x,y));
a[x][y].step=0;
v[x][y]=true;
while(!q.empty())
{
x=q.front().first;
y=q.front().second;
q.pop();
for(int i=0; i<4; i++)
{
int s=x+xx[i]; //上下左右
int e=y+yy[i];
if(s<1 || e<1 ||s>199 || e>199) continue;
if(a[x][y].f[i]==-1) //表示方向上出去了
{
printf("%d\n",a[x][y].step);
return ;
}
if(!v[s][e] && a[x][y].f[i]==0) //过门
{
v[s][e]=true;
a[s][e].step=a[x][y].step+1;
q.push(pair<int, int>(s,e));
}
}
}
printf("-1\n");
}
int main()
{
int n,m;
while(~scanf("%d%d",&n,&m))
{
if(n==-1 && m==-1) break;
for(int i=0; i<N; i++)
{
for(int j=0; j<N; j++)
{
a[i][j].f[0]=-1;
a[i][j].f[1]=-1;
a[i][j].f[2]=-1;
a[i][j].f[3]=-1;
a[i][j].step=0;
}
}
while(n--) //墙
{
int x,y,d,t;
scanf("%d%d%d%d",&x,&y,&d,&t); //格子左下角的坐标标记整个格子
if(d) // 墙与y轴平行
{
for(int i=0; i<t; i++)
{
a[x][y+i].f[2]=1; //点(x,y)向上t格的左边标记为墙
if(x>1) //当横坐标为1的时候,左面没有格子
a[x-1][y+i].f[3]=1; //点(x,y)左面的格子(x-1,y)的右面标记为墙
}
}
else //墙与x轴平行
{
for(int i=0; i<t; i++)
{
a[x+i][y].f[1]=1; //点(x,y)向右t格的下边标记为墙
if(y>1) //当纵坐标为1的时候,下面没有格子
a[x+i][y-1].f[0]=1; //点(x,y)下面的格子(x,y-1)的上面标记为墙
}
}
}
while(m--) //门,同墙
{
int x,y,d;
scanf("%d%d%d",&x,&y,&d);
if(d)
{
a[x][y].f[2]=0;
if(x>1)
a[x-1][y].f[3]=0;
}
else
{
a[x][y].f[1]=0;
if(y>1)
a[x][y-1].f[0]=0;
}
}
double s,e;
memset(v,false,sizeof(v));
cin>>s>>e;
if( s<1 || s>199 || e<1 || e>199) //没有这个会RE , 死孩子在外面的时候
{
printf("0\n");
continue;
}
bfs((int)s,int(e));
}
return 0;
}