输入样例#1:
5 4
##.#
##S#
#…#
#.##
#…#
5 4
##.#
##S#
#…#
…#.
#.##
输出样例#1:
Yes
No
大概就是说给出一个01迷宫类的地图,按照这个地图来扩展新地图,类似这样,然后问你是不是###可以走无限远。
搜索结束的条件为重复到达地图的某个点且实际横纵坐标与上一次访问时的不同即可。注意也要判断在同一个小地图里,某个点是否被重复访问,不然会死循环。
注意的点:
1.当能以不同实际坐标访问地图的某个节点时,表示符合题意,输出Yes,判断的时候是判断vis[gx][gy][1] != sjx || vis[gx][gy][2] != sjy,而不是&&
2.判断某个节点是否以相同的实际坐标访问,起到普通dfs的vis数组的作用
3.搜索的时候判断ans是否为1,可以加快搜索。
代码:
#include<iostream>
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<string>
#include<algorithm>
#include<vector>
#include<queue>
#include<sstream>
#include<stack>
#include<stdio.h>
using namespace std;
int n, m;
const int maxn = 1505;
int g[maxn][maxn];
int vis[maxn][maxn][3]; //0存储是否被访问,1,2位存储上一次访问这个点的“实际坐标”
int sx, sy; //开始的坐标
char hh[10];
char c;
int ans;
int dir[4][2] = { {0,1},{0,-1}, {1,0}, {-1,0} };
void dfs(int sjx, int sjy, int gx, int gy) {
if (ans)
return;
if (vis[gx][gy][0] && (vis[gx][gy][1] != sjx || vis[gx][gy][2] != sjy)) {//表示以不同实际结点第二次访问到这里,注意这里是||
ans = 1;
return;
}
if (vis[gx][gy][0]) { //避免重复访问某个实际结点
return;
}
//cout << sjx << " " << sjy << " " << gx << " " << gy << endl;
vis[gx][gy][0] = 1; vis[gx][gy][1] = sjx; vis[gx][gy][2] = sjy;
for (int i = 0; i < 4; i++) {
int sjxx = sjx + dir[i][0];
int sjyy = sjy + dir[i][1];
int gxx = (gx + dir[i][0] + n) % n;
int gyy = (gy + dir[i][1] + m) % m;
if (g[gxx][gyy])
dfs(sjxx, sjyy, gxx, gyy);
}
}
int main() {
while (~scanf("%d%d", &n, &m)) {
memset(g, 0, sizeof g);
memset(vis, 0, sizeof vis);
ans = 0;
for (int i = 0; i < n; i++) {//输入,1表示可走,0表示墙
gets_s(hh); //读掉换行符
for (int j = 0; j < m; j++) {
scanf("%c", &c);
if (c == 'S') {
g[i][j] = 1;
sx = i; sy = j;
}
else if (c == '.')
g[i][j] = 1;
}
}
dfs(sx, sy, sx, sy);
if (ans)
cout << "Yes" << endl;
else
cout << "No" << endl;
}
return 0;
}