Problem 洛谷P1363-幻想迷宫
Accept: 1.1k Submit: 6.1k
Time Limit: 1000 mSec Memory Limit : 128MB
Problem Description
背景 Background
(喵星人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就只好启动城堡的毁灭程序了……当然不到万不得已,他不想这么做。。。
Input
输入包含多组数据,以EOF结尾。
每组数据的第一行是两个整数N、M。
接下来是一个N*M的字符矩阵,表示迷宫里(0,0)到(n-1,m-1)这个矩阵单元。
Output
对于每组数据,输出一个字符串,Yes或者No。
Sample Input
5 4
##.#
##S#
#..#
#.##
#..#
5 4
##.#
##S#
#..#
..#.
#.##
Sample output
No
说明
数据范围和注释
对于30%的数据,N,M<=20
对于50%的数据,N.M<=100.
对于100%的数据,N,M<=1500,每个测试点不超过10组数据.
题解:这个题还是挺有意思的,第一反应是DFS搜一下联通块,看边界,如果边界有对称的能到达的,肯定能无限走下去,然后很愉快地WA了......
上述判据充分不必要,虽然不对,但是还是给接下来的做法提供了思路,画个图就知道为啥不对,把这个迷宫复制成3*3(我画的时候画的是2*2),比如向右到达一个扩展的迷宫,这个时候再到达下面的扩展的的迷宫,和从原始迷宫到达下面的扩展来的迷宫肯定是不一样的,怎么解决这个冲突,最原始的想法是给这9个迷宫编上号,vis数组标记不同的迷宫,如果一个在取模意义下相同的格子被标记了不同的编号,那就肯定可以走无限远,但是这样实现起来很不方便,导致代码贼长,看了别人的题解,发现了一个非常机智的做法,vis数组加一维,最后一维只有0、1、2,0用来记录有没有到达过,1、2分别记录没有取模的横纵坐标,每次向四周延伸的时候,如果还没有被遍历过,那就是普通的标记,如果已经被遍历过,那就比较当前未取模的坐标和这个点记录的未取模坐标是否相同,相同就代表着是在同一个迷宫第二次遇到,忽略,不同就代表着在不同的迷宫遇到了同一个格子,自然能够走无限远。
1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 #include <cstdlib> 5 using namespace std; 6 7 const int maxn = 1500+10; 8 int n,m; 9 int sx,sy; 10 int dir[4][2] = {{1,0},{-1,0},{0,1},{0,-1}}; 11 char gra[maxn][maxn]; 12 int vis[maxn][maxn][3]; 13 bool flag; 14 15 void dfs(int x,int y){ 16 if(flag) return; 17 int xx,yy,r,c; 18 for(int i = 0;i < 4;i++){ 19 xx = vis[x][y][1]+dir[i][0],yy = vis[x][y][2]+dir[i][1]; 20 r = (x+dir[i][0]+n)%n,c = (y+dir[i][1]+m)%m; 21 if(gra[r][c] != '#'){ 22 if(!vis[r][c][0]){ 23 vis[r][c][0] = 1; 24 vis[r][c][1] = xx,vis[r][c][2] = yy; 25 dfs(r,c); 26 } 27 else{ 28 if(vis[r][c][1]!=xx || vis[r][c][2]!=yy){ 29 flag = true; 30 return; 31 } 32 } 33 } 34 } 35 } 36 37 int main() 38 { 39 //freopen("input.txt","r",stdin); 40 while(~scanf("%d%d",&n,&m)){ 41 memset(vis,0,sizeof(vis)); 42 flag = false; 43 for(int i = 0;i < n;i++){ 44 scanf("%s",gra[i]); 45 for(int j = 0;j < m;j++){ 46 if(gra[i][j] == 'S') gra[i][j]='.',sx = i,sy = j; 47 } 48 } 49 vis[sx][sy][0] = 1; 50 vis[sx][sy][1] = sx,vis[sx][sy][2] = sy; 51 dfs(sx,sy); 52 if(!flag) printf("No "); 53 else printf("Yes "); 54 } 55 return 0; 56 }