逃离迷宫
Time Limit: 1000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 34599 Accepted Submission(s): 8478
Problem Description
给定一个m
× n (m行,
n列)的迷宫,迷宫中有两个位置,gloria想从迷宫的一个位置走到另外一个位置,当然迷宫中有些地方是空地,gloria可以穿越,有些地方是障碍,她必须绕行,从迷宫的一个位置,只能走到与它相邻的4个位置中,当然在行走过程中,gloria不能走到迷宫外面去。令人头痛的是,gloria是个没什么方向感的人,因此,她在行走过程中,不能转太多弯了,否则她会晕倒的。我们假定给定的两个位置都是空地,初始时,gloria所面向的方向未定,她可以选择4个方向的任何一个出发,而不算成一次转弯。gloria能从一个位置走到另外一个位置吗?
Input
第1行为一个整数t (1 ≤ t ≤ 100),表示测试数据的个数,接下来为t组测试数据,每组测试数据中,
第1行为两个整数m, n (1 ≤ m, n ≤ 100),分别表示迷宫的行数和列数,接下来m行,每行包括n个字符,其中字符\'.\'表示该位置为空地,字符\'*\'表示该位置为障碍,输入数据中只有这两种字符,每组测试数据的最后一行为5个整数k, x1, y1, x2, y2 (1 ≤ k ≤ 10, 1 ≤ x1, x2 ≤ n, 1 ≤ y1, y2 ≤ m),其中k表示gloria最多能转的弯数,(x1, y1), (x2, y2)表示两个位置,其中x1,x2对应列,y1, y2对应行。
Output
每组测试数据对应为一行,若gloria能从一个位置走到另外一个位置,输出“yes”,否则输出“no”。
Sample Input
2
5 5
...**
*.**.
.....
.....
*....
1 1 1 1 3
5 5
...**
*.**.
.....
.....
*....
2 1 1 1 3
Sample Output
no
yes
总的来说这道题真的很为难人,要用到广度优先搜索。看了很多人的博客,都没看懂,所以说编码习惯真的很重要,要记得写注释啊。这道题怎么说呢,就是从始点开始,上下左右直走,直到没有路或者到达终点为止,如果是没有路,就从这条路的最开始开始,上下左右直走,和上一个情况一样。就这样将一整个图遍历完如果还没有到达终点就没有方法到达终点,有种回溯法的意思。
#include<stdio.h>
#include<iostream>
#include<queue>
#include<string.h>
using namespace std;
char map[110][110];
bool vis[110][110];
int sx,sy,ex,ey,n,m,k;//sx,sy,ex,ey,分别是开始的坐标和结束的坐标
int fangxiang[4][2]={-1,0,0,1,1,0,0,-1};
struct node
{
int x,y;
int step;
}s,e; //s为定点,e为扩展点//
//队列中的一个元素,也就是每个节点包括三个元素,两个位置元素,一个当前走到当前节点的时候的拐弯次数//
bool judge(int x,int y)
{
if(x>=1&&x<=n&&y>=1&&y<=m&&map[x][y]==\'.\') //判断当前的扩展节点是否符合要求,既不能走到迷宫外面,不能走有障碍的地方//
return true;
else
return false;
}
void BFS()
{
queue<node>qu;
int i,j;
if(sx==ex&&sy==ey) //如果起点就是终点,那么输出然后退出//
{
printf("yes\n");
return;
}
s.x=sx;s.y=sy;s.step=-1; //设置第一个定点//
vis[sx][sy]=true; //标记起点//
qu.push(s);
while(!qu.empty())
{
s=qu.front(); //取起点为定点//
qu.pop(); //弹出//
for(i=0;i<4;i++)
{
int tx=s.x+fangxiang[i][0]; //向四个方向走//
int ty=s.y+fangxiang[i][1];
while(judge(tx,ty)) //如果这个点满足条件//
{
//是否已经走过,因为该BFS是一次性把某一个方向都搜完,所以如果已经搜索过,那么再走这一条路的任何一个定点的时候它都不会转弯//
if(vis[tx][ty]==false)
{
vis[tx][ty]=true; //标记//
e.x=tx;
e.y=ty;
e.step=s.step+1;
qu.push(e); //扩展点入队列//
if(e.x==ex&&e.y==ey&&e.step<=k) //每加入一个新的定点,就开始判断是不是到了终点//
{
printf("yes\n");
return ;
}
}
tx+=fangxiang[i][0];//把一个方向上的所有可以走成路的点搜索一遍,直到不符合要求
ty+=fangxiang[i][1];
//之所以要把定点的四周的所有的定点都如队列,是因为,题目中要求了拐弯数,step初始化为-1,第一个定点为起点之后走的第一个点不算是拐弯数,所以+1等于0 。该题的思路也就是运用BFS的同时,考虑到拐弯数这个条件,把step=0的节点先入队列,因为第一个走的肯定是他们其中的一个,之后再以他们为定点走的扩展点,step一次增加,因为无论向哪个方向走都会拐弯。之后以此类推,把step=1.=2的点都入队列
}
}
}
printf("no\n");
return ;//必须要有return
//能够走到终点的条件一个是起点就是终点另一个就是扩展点就是终点,如果这两个都不是,那么就是走不到终点,可以退出了//
}
int main()
{
int N;
int i;
while(scanf("%d",&N)!=EOF)
{
while(N--)
{
memset(vis,false,sizeof(vis));//初始化vis
memset(map,0,sizeof(map)); //初始化 map
scanf("%d %d",&n,&m);
for(i=1;i<=n;i++)
scanf("%s",map[i]+1);
scanf("%d%d%d%d%d",&k,&sy,&sx,&ey,&ex);
BFS();
}
}
return 0;
}