题目信息
解题思路
在这里可怜喵星人一秒钟,然后我们开始讲题…
这道题明显是用搜索的 ,题目里的迷宫很容易让人想到dfs。
显然,我们可以把输入的一个迷宫变成九个迷宫,判断从起点(x, y)能否走到(x + n, y),(x - n, y),(x, y + m)或(x, y - m)。
但是大家会发现,这样的空间复杂度是很大哒,明显会MLE。
所以我们直接对迷宫去mod就好啦。
但是,如果走到过一个点又走到了这个点,那是可以走∞远的。
这里又出现了一大大大大大大堆问题。
想到这蒟蒻君也懵(´・ω・`)了…
参考网上大佬的题解后发现还有一个巧妙的方法…
我们记录取模的横纵坐标x, y,同时记录没有取模的坐标X, Y
当第一次走这个迷宫的时候,x, y和X, Y肯定是相等的。
所以只要走到的一个点的x, y和X, Y不相等,那这个点一定是被走了第二遍。
代码实现
建议先看一下蒟蒻君的dfs。
算法初探系列2——深度优先搜索之计算思维
#include <bits/stdc++.h>
using namespace std;
const int N = 1505;
const int dir_arr[4][2] = {{1, 0}, {-1, 0}, {0, 1}, {0, -1}}; // 方向数组
int n, m;
int st_x, st_y; // 起点坐标
int vis[N][N][3];
bool flag, a[N][N]; // a[i][j]表示(i, j)是否可走,0表示可以
void dfs(int x, int y, int X, int Y) {
if (flag) {
return ;
}
// 具体含义见分析过程
if (vis[x][y][0] && (vis[x][y][1] != X || vis[x][y][2] != Y)) {
flag = true;
return;
}
vis[x][y][0] = 1;
vis[x][y][1] = X;
vis[x][y][2] = Y;
for (int i = 0; i < 4; ++i) {
int nxt_x = (x + dir_arr[i][0] + n) % n; // 不要忘记每轮的mod
int nxt_y = (y + dir_arr[i][1] + m) % m;
int nxt_X = X + dir_arr[i][0];
int nxt_Y = Y + dir_arr[i][1];
if (!a[nxt_x][nxt_y]) {
if (vis[nxt_x][nxt_y][1] != nxt_X ||
vis[nxt_x][nxt_y][2] != nxt_Y ||
!vis[nxt_x][nxt_y][0]) {
dfs(nxt_x, nxt_y, nxt_X, nxt_Y);
}
}
}
}
int main() {
while (cin >> n >> m) {
// 不要忘记每轮初始化
flag = false; // flag表示每轮答案
memset(a, false, sizeof(a));
memset(vis, false, sizeof(vis));
for (int i = 0; i < n; ++i) {
for (int j = 0; j < m; ++j) {
char ch;
cin >> ch;
if (ch == '#') { // 不能走到墙上
a[i][j] = 1;
}
if (ch == 'S') { // 记录起点坐标
st_x = i;
st_y = j;
}
}
}
// 从起点开始尝试
dfs(st_x, st_y, st_x, st_y); // st_x和st_y取不取mod都是本身
if (flag == true) {
cout << "Yes\n";
} else {
cout << "No\n";
}
}
return 0;
}