题目:https://www.luogu.org/problemnew/show/P1363
搜索:https://blog.csdn.net/weixin_39778570/article/details/86484062
ACM题集:https://blog.csdn.net/weixin_39778570/article/details/83187443
有一个矩阵,可以无限扩张(向四周重复自己)
问,点S能否遍历往无限远处
----------------------------------------
很显然,如果不同矩阵上的点可以遍历两次则说明他可以遍历往无限远处
具体做法,我们把幻阵映射到原阵上,dfs(幻阵)
两次幻阵不一样则说明同一个点在不同阵上被遍历到了
#include<bits/stdc++.h>
#define ll long long
#define fo(i,j,n) for(register int i=j; i<=n; ++i)
#define R register int
using namespace std;
const int dx[] = {-1,1,0,0};
const int dy[] = {0,0,-1,1};
int n,m,vis[3][1600][1600];
char mp[1600][1600];
bool ans;
// (x,y)为原阵上的点,(fx,fy)为幻阵上的点(未取模)
inline void dfs(int x, int y, int fx, int fy){ // falsex
if(ans)return;
// 如果已经访问过,并且两次幻阵坐标不同,说明访问过两次原阵
if(vis[0][x][y] && (vis[1][x][y]!=fx || vis[2][x][y]!=fy)){
ans = 1;
return;
}
// 标记原阵已经访问过,并且记录幻阵坐标
vis[0][x][y]=1,vis[1][x][y]=fx,vis[2][x][y]=fy;
fo(i,0,3){
int nowx = (x+dx[i]+n)%n;
int nowy = (y+dy[i]+m)%m;
int nowfx = fx+dx[i];
int nowfy = fy+dy[i];
if(mp[nowx][nowy]!='#'){
// 未访问过,或者访问不同的点
if(!vis[0][nowx][nowy] || vis[1][nowx][nowy]!=nowfx || vis[2][nowx][nowy]!=nowfy){
dfs(nowx,nowy,nowfx,nowfy);
}
}
}
}
int main(){
while(scanf("%d%d",&n,&m)!=EOF){
int x,y,flag=0;
for(R i=0; i<n; i++){
scanf("%s",mp[i]);
if(flag)continue;
for(R j=0; j<m; j++){
if(mp[i][j]=='S'){
x = i;
y = j;
flag = 1;
}
}
}
ans = 0;
memset(vis[0], 0, sizeof(vis[0]));
dfs(x,y,x,y);
if(ans)puts("Yes");
else puts("No");
}
return 0;
}