洛谷P1363 幻想迷宫【dfs】

无限地图DFS搜索
本文介绍了一个关于无限重复地图上的DFS搜索算法实现。通过利用取模技巧,将无限地图压缩到有限大小,使用vis数组记录每个点的访问状态及对应的实际坐标,判断是否能从起点走到无限远的地方。

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

题意

有一个地图,起点是S,障碍物用#表示。可以将这个地图不断的在四周重复,问从起点开始是否可以走到无限远的地方去。

思路

刚开始想的是地图放中间,然后在四周都拼一个同样的,然后看看能不能走回到起点。

但是发现仅仅是拼四个是不够的,那拼九个?反正又是MLE又是WA的。

主要思路还是dfs搜索,题目中其实给了提示了,可以利用取模。

把每一次走的位置都压缩到一个地图上去。但是又去标记这是在那一块被访问到的。

如果可以两次走到这个点(其实并不是走到这个点而是走到另一块的对应位置)就说明可以走到无限远的地方。

所以我们需要个vis数组。第一个用来标记这个点是否被访问过,第二三个用来标记访问到对应这个点时候的横纵坐标。

dfs时即需要知道当前的坐标,又需要知道取模之前实际的坐标。

如果之前走到这个点时候的横纵坐标和现在实际的坐标是相同的,说明走到的是同一个点,如果有一个是不同的说明已经走到另一块地图上去了。

 1 //#include<bits/stdc++>
 2 #include<stdio.h>
 3 #include<iostream>
 4 #include<algorithm>
 5 #include<cstring>
 6 #include<stdlib.h>
 7 #include<queue> 
 8 #include<map>
 9 #include<stack>
10 #include<set>
11 
12 #define LL long long
13 #define ull unsigned long long
14 #define inf 0x7f7f7f7f 
15 
16 using namespace std;
17 
18 int n, m;
19 const int maxn = 1505;
20 char gra[maxn][maxn];
21 int vis[maxn][maxn][3];
22 int dx[4] = {0, 0, -1, 1};
23 int dy[4] = {1, -1, 0, 0};
24 int stx, sty;
25 
26 bool check(int x, int y)
27 {
28     if(x < 0 || y < 0 || x >= n || y >= m)return false;
29     else return true;
30 }
31 
32 bool ans;
33 void dfs(int x, int y, int acx, int acy)
34 {
35     if(vis[x][y][0] && vis[x][y][1] == acx && vis[x][y][2] == acy){
36         
37         return;
38     }
39     else if(vis[x][y][0] && (vis[x][y][1] != acx || vis[x][y][2] != acy)){
40         ans = true;
41         return;    
42     }
43     vis[x][y][0] = true;
44     vis[x][y][1] = acx;
45     vis[x][y][2] = acy;
46     for(int i = 0; i < 4; i++){
47         int tox = (x + dx[i] + n) % n, toy = (y + dy[i] + m) % m;
48         if(check(tox, toy) && gra[tox][toy] != '#'){
49             dfs(tox, toy, acx + dx[i], acy + dy[i]);
50         }
51     }
52     return;
53 }
54 
55 int main()
56 {
57     while(scanf("%d%d", &n, &m) != EOF){
58         memset(gra, 0, sizeof(gra));
59         memset(vis, 0, sizeof(vis));
60         ans = false;
61         for(int i = 0; i < n; i++){
62             cin>>gra[i];
63             for(int j = 0; j < m; j++){
64                 if(gra[i][j] == 'S'){
65                     stx = i;
66                     sty = j;
67                 }
68             }
69         }
70         
71         dfs(stx, sty, stx, sty);//vis[stx][sty][0] = true;
72         if(ans)printf("Yes\n");
73         else printf("No\n");
74     }
75     
76     return 0;    
77 } 

 

转载于:https://www.cnblogs.com/wyboooo/p/10960351.html

### 迷宫问题的DFS解决方案 深度优先搜索(Depth First Search, DFS)是一种常用的图遍历算法,在解决迷宫问题时非常有效。以下是基于提供的引用以及专业知识整理的一个完整的解决方案。 #### 1. 基本思路 DFS的核心在于通过递归的方式探索所有的可能路径,直到找到目标位置或者确认无路可走为止。对于迷宫问题来说,通常会定义一个二维数组表示地图,其中 `0` 表示可以通过的位置,而 `1` 或其他标记则代表障碍物[^1]。 为了实现这一功能,可以采用如下策略: - 定义四个移动方向:上、下、左、右。 - 使用递归来尝试每一步的可能性,并在遇到死胡同时返回前一状态继续探索新的分支[^4]。 #### 2. 实现细节 下面给出了一种典型的C++代码实现方式: ```cpp #include <iostream> #include <vector> using namespace std; // 方向数组,分别对应上下左右四个方向 const vector<pair<int, int>> directions = { { -1, 0 }, // 上 { 1, 0 }, // 下 { 0, -1 }, // 左 { 0, 1 } // 右 }; bool isValidMove(int newRow, int newCol, const vector<vector<int>>& maze, vector<vector<bool>>& visited) { int rows = maze.size(); int cols = maze[0].size(); return newRow >= 0 && newRow < rows && newCol >= 0 && newCol < cols && !maze[newRow][newCol] && !visited[newRow][newCol]; } bool dfs(vector<vector<int>>& maze, vector<vector<bool>>& visited, pair<int, int> currentPos, pair<int, int> target) { if (currentPos.first == target.first && currentPos.second == target.second){ return true; } for(auto& dir : directions){ int newRow = currentPos.first + dir.first; int newCol = currentPos.second + dir.second; if(isValidMove(newRow, newCol, maze, visited)){ visited[newRow][newCol] = true; if(dfs(maze, visited, make_pair(newRow, newCol), target)){ return true; } // 如果该条路径不通,则回溯到之前的状态并尝试另一条路径 } } return false; } int main(){ vector<vector<int>> maze = { {0, 1, 0, 0}, {0, 1, 0, 1}, {0, 0, 0, 0}, {0, 1, 1, 0} }; pair<int,int> start = {0,0}; pair<int,int> end = {3,3}; int nRows = maze.size(); int nCols = maze[0].size(); vector<vector<bool>> visited(nRows, vector<bool>(nCols, false)); bool result = dfs(maze, visited, start, end); cout << (result ? "Path found!" : "No path exists.") << endl; return 0; } ``` 上述程序中包含了几个重要部分: - **方向数组**用于指定每次可以从当前位置出发到达的新坐标; - **isValidMove函数**用来判断下一步是否合法; - **dfs函数**实现了核心逻辑,即不断深入直至达到目的地或穷尽所有可能性后退出[^2]。 #### 3. 关键点解析 - **边界条件处理**: 需要特别注意越界情况以及访问过的节点不能再重复进入以免陷入无限循环[^3]。 - **回溯机制**: 当某一条路线无法通达终点时,应回退至上一层重新选择未被尝试的方向前进。 --- ###
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值