3046: 【普及+/提高】【P1363】幻象迷宫
内存限制:128 MB
时间限制:1.000 S
评测方式:文本比较
命题人:
提交:8
解决:4
题目描述
幻象迷宫可以认为是无限大的,不过它由若干个N*M的矩阵重复组成。矩阵中有的地方是道路,用'.'表示;有的地方是墙,用'#'表示。LHX和WD所在的位置用'S'表示。也就是对于迷宫中的一个点(x,y),如果(x mod n,y mod m)是'.'或者'S',那么这个地方是道路;如果(x mod n,y mod m)是'#',那么这个地方是墙。LHX和WD可以向上下左右四个方向移动,当然不能移动到墙上。
请你告诉LHX和WD,它们能否走出幻象迷宫(如果它们能走到距离起点无限远处,就认为能走出去)。如果不能的话,LHX就只好启动城堡的毁灭程序了……当然不到万不得已,他不想这么做。。。
输入
输入包含多组数据,以EOF结尾。
每组数据的第一行是两个整数N、M。
接下来是一个N*M的字符矩阵,表示迷宫里(0,0)到(n-1,m-1)这个矩阵单元。
输出
对于每组数据,输出一个字符串,Yes或者No。
样例输入 复制
5 4
##.#
##S#
#..#
#.##
#..#
5 4
##.#
##S#
#..#
..#.
#.##
样例输出 复制
Yes
No
提示
对于30%的数据,N,M<=20
对于50%的数据,N.M<=100.
对于100%的数据,N,M<=1500,每个测试点不超过10组数据.
BFS:
#include<bits/stdc++.h>
using namespace std;
const int N = 1510;
struct coord {
int x;
int y;
};
//路径中的某个点,如果再次被访问到,并且,不是原来的前驱时,就可以交替进行这样的操作,不断外延出去。
//走迷宫下右上左
int dx[4] = {0, 1, 0, -1};
int dy[4] = {1, 0, -1, 0};
int n, m;
int sx, sy;//出发点坐标
char g[N][N]; //地图
int book[N][N][3]; // book[ u ][v][0]:是否访问过,book[ u ][v][1]:x,book[ u ][v][2]:y
/**
* 功能:正数+负数取模
*/
int MOD(int a, int b) {
return (a % b + b) % b;
}
//广度优先搜索
bool bfs() {
queue<coord> q; //声明队列
q.push({sx, sy}); //将出发点放入队列
//标识起点已使用,并且第一次到达时,真实坐标是x,y
book[sx][sy][0] = 1, book[sx][sy][1] = sx, book[sx][sy][2] = sy;
//开始套路
while (!q.empty()) {
int x = q.front().x;
int y = q.front().y;
q.pop();
for (int i = 0; i < 4; ++i) {
int tx = x + dx[i];
int ty = y + dy[i];
//因为可能出现负数,使用负数取模运算
int u = MOD(tx, n), v = MOD(ty, m);
//如果不是墙
if (g[ u ][v] != '#') {
//如果走过.而且与上次过来的位置不一样的话,就是肯定能走出去
if (!book[ u ][v][0]) {
//没有走过,入队列
q.push({tx, ty});
//标识已使用,并且第一次到达的坐标是a,b
book[ u ][v][0] = 1, book[ u ][v][1] = tx, book[ u ][v][2] = ty;
} else if ((book[ u ][ v ][1] != tx || book[ u ][v][2] != ty)) return true;
}
}
}
return false;
}
int main() {
while (cin >> n >> m) {
//每次清空,地图数组不用每次清空,因为每次都全新读入,自
memset(book, 0, sizeof book);
//双重循环读入地图
// 注意i是从0开始,到n-1结束,这是因为:表示迷宫里(0,0)到(n-1,m-1)这个矩阵单元。
// 注意j是从0开始,到m-1结束,这是因为:表示迷宫里(0,0)到(n-1,m-1)这个矩阵单元。
for (int i = 0; i < n; ++i)
for (int j = 0; j < m; ++j) {
cin >> g[i][j];
if (g[i][j] == 'S')sx = i, sy = j; //标识起点
}
//广度优先
if (bfs())cout << "Yes" << endl; //可以走出幻象迷宫
else cout << "No" << endl; //不能走出幻象迷宫
}
}