题解 CF196B Infinite Maze
思路就是标记走过的点,判断是否能从某个点走到另一幅图的这个点。
对于一个点,我们用\(x,y\)作为它在单个迷宫中的坐标,\(nx,ny\)作为它在整个迷宫中的实际坐标。
普通\(dfs\)中的\(vis\)数组一般记录了某个点是否走过,但在这题中,由于我们不好控制\(dfs\)走的方向,有可能走回一个标记的点,而迷宫又是无限的,所以我们把\(vis\)加上两个维度标记上次是在整个迷宫的哪个点走到的,如果再次走到该点且当前在整个迷宫的坐标不等于上次来到该点的坐标,就判断能走出迷宫
#include<bits/stdc++.h>
#define int long long
using namespace std;
const int gox[4]={1,-1,0,0},goy[4]={0,0,1,-1};
int n,m,vis[1505][1505][3];
bool flag,a[1505][1505];
void dfs(int x,int y,int nx,int ny){
if(flag)return;
if(vis[x][y][0]&&(vis[x][y][1]!=nx||vis[x][y][2]!=ny)){//在小迷宫中走过该点且上次走到该点坐标不同,则以走出迷宫
flag=1;
return;
}
vis[x][y][0]=1;vis[x][y][1]=nx;vis[x][y][2]=ny;//标记nx和ny
for(int i=0;i<4;i++){
int p=(x+gox[i]+n)%n,q=(y+goy[i]+m)%m;//+n和+m保证p,q不为负数
int np=nx+gox[i],nq=ny+goy[i];
if(!a[p][q]){
if(!vis[p][q][0]||vis[p][q][1]!=np||vis[p][q][2]!=nq)//只要没去过或者上次坐标与这次不相等就走
dfs(p,q,np,nq);
}
}
}
signed main(){
ios::sync_with_stdio(false);//cincout优化
cin>>n>>m
flag=0;
memset(a,0,sizeof(a));
memset(vis,0,sizeof(vis));
int stx,sty;char ch;
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("No");
else puts("Yes");
return 0;
}