题目链接:P1363 幻象迷宫 - 洛谷 | 计算机科学教育新生态
个人想法:开始以为只要判断能不能走到终点,后面多读了几遍题目发现这个迷宫是无限大的,(学好语文很重要~~~),想了一会不会于是去看大佬的思路。
解题思路:整个迷宫是由 N*M 小迷宫无限扩展形成的,想要走到无限远的地方,那就应该走出很远后,又能到达某个走过的点(这个走过是指,相对小迷宫的位置已经被走过了),所以我们只要判断这个点是否被走过就行了,如何判断:设(x,y)未走过的位置,当坐标超出边界时对其取模,同时用(lx,ly)记录真实位置,并记录(x,y)走过,当再次走到该点时对比此时真实的和原来存储的,如果不一样说明找到了一条可以无限走的路
代码部分:
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N = 1510;
const int dx[4] = {1,-1,0,0},dy[4] = {0,0,1,-1};//用偏移量来表示向上下左右 走
int n,m;//n*m的迷宫
int stx,sty;//记录起始所在位置
int vis[N][N][3];
bool flag,a[N][N];//flag记录答案,a记录那些位置可以走
char ch;
//vis[x][y][0]记录该点是否走过, vis[x][y][1]记录该点真实x坐标,vis[x][y][2] 记录真实的y坐标
int read()
{
int t = 0, f = 1;
char ch = getchar();
while(ch > '9' || ch < '0') {
if(ch == '-') f = -1;
ch = getchar();
}
while(ch <= '9' && ch >= '0') {
t = t * 10 + ch - '0';
ch = getchar();
}
return t * f;
}
void dfs(int x,int y,int lx,int ly)
{
if(flag) return;
if(vis[x][y][0] && (vis[x][y][1] != lx || vis[x][y][2] != ly))//如果可以走并且记录的为欧洲和上次不一样说明找到了答案
{
flag = true;
return;
}
vis[x][y][1] = lx, vis[x][y][2] = ly, vis[x][y][0] = 1;
for(int i = 0; i < 4; i++)
{
int xx = (x + dx[i] + n) % n, yy = (y + dy[i] + m) % m;
int lxx = lx + dx[i], lyy = ly + dy[i];
if(!a[xx][yy])
{
if(vis[xx][yy][1] != lxx || vis[xx][yy][2] != lyy || !vis[xx][yy][0])
dfs(xx,yy,lxx,lyy);
}
}
}
int main()
{
ios::sync_with_stdio(false);
cin.tie(0),cout.tie(0);
while(cin >> n >> m) {
flag = 0;
memset(a, 0, sizeof(a));
memset(vis, 0, sizeof(vis));
for(int i=0; i<n; ++i)
for(int j=0; j<m; ++j) {
cin >> ch;
if(ch == '#') a[i][j] = 1;
if(ch == 'S') stx = i, sty = j;
}
dfs(stx, sty, stx, sty);
if(flag) puts("Yes");
else puts("No");
}
return 0;
}