题目描述
(喵星人LHX和WD同心协力击退了汪星人的入侵,不幸的是,汪星人撤退之前给它们制造了一片幻象迷宫。)
WD:呜呜,肿么办啊……
LHX:momo...我们一定能走出去的!
WD:嗯,+U+U!
描述 Description
幻象迷宫可以认为是无限大的,不过它由若干个N*M的矩阵重复组成。矩阵中有的地方是道路,用'.'表示;有的地方是墙,用'#'表示。LHX和WD所在的位置用'S'表示。也就是对于迷宫中的一个点(x,y),如果(x mod n,y mod m)是'.'或者'S',那么这个地方是道路;如果(x mod n,y mod m)是'#',那么这个地方是墙。LHX和WD可以向上下左右四个方向移动,当然不能移动到墙上。
请你告诉LHX和WD,它们能否走出幻象迷宫(如果它们能走到距离起点无限远处,就认为能走出去)。如果不能的话,LHX就只好启动城堡的毁灭程序了……当然不到万不得已,他不想这么做。。。
解析
显然,对于这样无限大的一个迷宫,由于其具有分形的特点,只要能从任意单位矩阵的一点的位置到达另一个单位矩阵的同一位置(相对本单位矩阵的位置),那么其它矩阵的这个点就可以到达,意味着能走出去。
貌似这题的数据不卡单位矩阵可走路径成环的情况,但是窝不知道窝想了好久。。。
对于另一种情况,且无环,如果我们走回到了某个曾经走过的点的位置(相对于无限的迷宫的位置),说明走不出去了。
因此,我们要记录:走到某一位置的相对单位矩阵的坐标和相对整个迷宫的坐标,以及这个位置是否走过。
参考代码
#include<cstdio> #include<iostream> #include<cmath> #include<cstring> #include<ctime> #include<cstdlib> #include<algorithm> #include<queue> #include<set> #include<map> #define N 1510 using namespace std; int n,m; char a[N][N]; int v[3][N][N]; int dir[4][2]={{1,0},{-1,0},{0,1},{0,-1}}; inline bool dfs(int x,int y,int px,int py) { if(v[0][px][py]&&(v[1][px][py]!=x||v[2][px][py]!=y)) return 1; if(v[0][px][py]&&v[1][px][py]==x&&v[2][px][py]==y) return 0; v[0][px][py]=1,v[1][px][py]=x,v[2][px][py]=y; for(int i=0;i<4;++i){ int nx=x+dir[i][0],ny=y+dir[i][1]; int mx=(px+dir[i][0]+n)%n,my=(py+dir[i][1]+m)%m;//防止数组溢出 if(a[mx][my]=='#') continue; if(dfs(nx,ny,mx,my)) return 1; } return 0; } int main() { while(~scanf("%d%d",&n,&m)){ memset(v,0,sizeof(v)); memset(a,0,sizeof(a)); for(int i=0;i<n;++i) scanf("%s",a[i]); for(int i=0;i<n;++i) for(int j=0;j<m;++j) if(a[i][j]=='S'){ if(dfs(i,j,i,j)) printf("Yes\n"); else printf("No\n"); break; } } return 0; }