【洛谷】【搜索(dfs)】P1363 幻想迷宮


【題目描述:】

幻象迷宮可以認為是無限大的,不過它由若干個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就只好啟動城堡的毀滅程序了……當然不到萬不得已,他不想這么做。

【輸入格式:】

輸入格式 InputFormat

輸入包含多組數據,以EOF結尾。

每組數據的第一行是兩個整數N、M。

接下來是一個N*M的字符矩陣,表示迷宮里(0,0)到(n-1,m-1)這個矩陣單元。

【輸出格式:】

輸出格式 OutputFormat

對於每組數據,輸出一個字符串,Yes或者No。

輸入樣例#15 4
##.#
##S#
#..#
#.##
#..#
5 4
##.#
##S#
#..#
..#.
#.##
輸出樣例#1: 
Yes
No
輸入輸出樣例

 

[算法分析:]

搜索時判斷能否重復到達某個點,當然迷宮的四個邊界是分別相通的。

一開始想的是:

如果從上(下)邊界的某個點能到達同一列下(上)邊界的某個點,或者是從左(右)邊界的某個點能夠到達同一行右(左)邊界的某個點,則可以走無限遠

但這樣的數據就會判斷錯誤:

3 5 S.#.. ##### #...# 

並不能直接從上面到達下面但也是可以到達的,而且枚舉邊界上的點再搜索會超時

 

然后想了一個比較正確(但還是不正確)的方法:

把讀入的一個迷宮變成九個迷宮,判斷從起點(x, y)能否走到(x + n, y)(x - n, y)(x, y + m)(x, y - m).

但這么做如果要走不止一個迷宮才能回到起點就GG

比如這組數據:

6 20
#.##.##.##.##.##.##.
#.##.##.##.##.##.##.
#.##.##.##.##.##.##.
S.#..#..#..#..#..#..
##..#..#..#..#..#..#
#..#..#..#..#..#..##

愉快地從下面跑到上面再跑到下面再...

顯然這種情況把1 * 1迷宮拓展成3 * 3是不可取的,而如果拓展成9 * 9(81 * 81)那一定是會爆內存的

 

所以不能拓展迷宮而對坐標取模就好了.

如果走到過某個點現在又走到了這個點,那顯然是可以走無限遠的。

現在出現了一些(堆)問題:

如何判斷是否走到過這個點呢?

有一個比較巧妙的方法:

記錄取模的橫縱坐標x, y時,同時記錄沒有取模的坐標lx, ly

當第一次走這個迷宮的時候,x, ylx, ly肯定是分別相等的

所以只要走到的一個點的x, ylx, ly不相等(x!=lx || y!=ly),那這個點一定是被走了第二遍.

 

[Code:]

 1 //P1363 幻想迷宮
 2 #include<iostream>
 3 #include<cstdio>
 4 #include<cstring>
 5 using namespace std;
 6 
 7 const int MAXN = 1500 + 1;
 8 const int dx[4] = {1, -1, 0, 0};
 9 const int dy[4] = {0, 0, 1, -1};
10 
11 int n, m;
12 int st_x, st_y;
13 int vis[MAXN][MAXN][3];
14 bool fl, a[MAXN][MAXN];
15 char ch;
16 
17 void dfs(int x, int y, int lx, int ly) {
18     if(fl) return;
19     if(vis[x][y][0] && (vis[x][y][1]!=lx || vis[x][y][2]!=ly)) {
20         fl = 1;
21         return;
22     }
23     vis[x][y][1] = lx, vis[x][y][2] = ly, vis[x][y][0] = 1;
24     for(int i=0; i<4; ++i) {
25         int xx = (x + dx[i] + n) % n, yy = (y + dy[i] + m) % m;
26         int lxx = lx + dx[i], lyy = ly + dy[i];
27         if(!a[xx][yy]) {
28             if(vis[xx][yy][1]!=lxx || vis[xx][yy][2]!=lyy || !vis[xx][yy][0])
29                 dfs(xx, yy, lxx, lyy);
30         }
31     }
32 }
33 int main() {
34     ios::sync_with_stdio(false);
35     while(cin >> n >> m) {
36         fl = 0;
37         memset(a, 0, sizeof(a));
38         memset(vis, 0, sizeof(vis));
39         for(int i=0; i<n; ++i)
40             for(int j=0; j<m; ++j) {
41                 cin >> ch;
42                 if(ch == '#') a[i][j] = 1;
43                 if(ch == 'S') st_x = i, st_y = j;
44             }
45         dfs(st_x, st_y, st_x, st_y);
46         if(fl) puts("Yes");
47         else puts("No");
48     }
49 }

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM