洛谷P1363-幻想迷宫

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

Yes
No
 

说明

数据范围和注释 

对于30%的数据,N,M<=20

对于50%的数据,N.M<=100.

对于100%的数据,N,M<=1500,每个测试点不超过10组数据.

 
题目链接:https://www.luogu.org/problemnew/show/P1363

题解:这个题还是挺有意思的,第一反应是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\n");
53         else printf("Yes\n");
54     }
55     return 0;
56 }

猜你喜欢

转载自www.cnblogs.com/npugen/p/9498233.html
今日推荐