迷宫
题目描述
给定一个m × n (m行, n列)的迷宫,迷宫中有两个位置,zzx想从迷宫的一个位置走到另外一个位置,当然迷宫中有些地方是空地,zzx可以穿越,有些地方是障碍,他必须绕行,从迷宫的一个位置,只能走到与它相邻的4个位置中,当然在行走过程中,zzx不能走到迷宫外面去。令人头痛的是,zzx是个没什么方向感的人,因此,他在行走过程中,不能转太多弯了,否则他会晕倒的。我们假定给定的两个位置都是空地,初始时,zzx所面向的方向未定,他可以选择4个方向的任何一个出发,而不算成一次转弯。zzx能从一个位置走到另外一个位置吗?
输入
第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表示zzx最多能转的弯数,(x1, y1), (x2, y2)表示两个位置,其中x1,x2对应列,y1, y2对应行。
输出
每组测试数据对应为一行,若zzx能从一个位置走到另外一个位置,输出“yes”,否则输出“no”。
样例输入
2
5 5
...**
*.**.
.....
.....
*....
1 1 1 1 3
5 5
...**
*.**.
.....
.....
*....
2 1 1 1 3
样例输出
no
yes
#include<iostream>
#include<queue>
#include<cstring>
using namespace std;
const int N = 1e2 + 10;
int s; // 输入样例个数
int n,m,x1,y1,x2,y2,k;
char g[N][N]; // 迷宫地图
bool st[N][N]; // 确定某个点是否被走过
int dx[4]={0,1,0,-1},dy[4]={1,0,-1,0}; // 坐标偏移量
// 定义节点变量 x,y为坐标 s 为 转弯次数
struct node{
int x,y,s;
};
// 判断这个点是否合法
// 在地图内 且可以走
bool check(int x,int y){
return x >= 1 && x <= n && y >= 1 && y <= m && g[x][y] == '.';
}
void bfs(){
queue<node> q; // 存储坐标点的队列
memset(st,0,sizeof st); // 初始化每个点都未走过
node next; // 起点
next.x = x1; // 起点初始化
next.y = y1;
next.s = -1;
q.push(next); // 将起点放入队列中
st[next.x][next.y]= true; // 起点置为走过
while(!q.empty()){ // 如果队列不为空
node a = q.front(); // 取出队头元素
q.pop(); // 出队
if(a.x == x2 && a.y == y2 && a.s <=k){ // 到达终点且转弯次数不超过k
puts("yes");
return;
}
for(int i = 0; i < 4;i++){ // 向四个方向出发
next.x = a.x + dx[i];
next.y = a.y + dy[i];
while(check(next.x,next.y)){
if(!st[next.x][next.y]){ //未走过 为false / 0
next.s = a.s + 1;
st[next.x][next.y] = true; // 走过
q.push(next);
}
next.x = next.x + dx[i]; // 同一个方向一直走直到不能走为止
next.y = next.y + dy[i]; // 转弯次数为 a.s+1
}
}
}
puts("no");
}
int main(){
cin >> s;
while(s--){
cin >> n >> m;
for(int i = 1; i <= n;i++){
for(int j = 1; j <= m;j++){
cin >> g[i][j];
}
}
cin >>k >> y1 >> x1 >> y2 >> x2;
bfs();
}
return 0;
}