当前位置:首页 > 洛谷 > 洛谷1363题解法:虚拟坐标优化BFS解决循环迷宫问题(附代码详解)

洛谷1363题解法:虚拟坐标优化BFS解决循环迷宫问题(附代码详解)

3个月前 (06-30)

洛谷1363题解法:虚拟坐标优化BFS解决循环迷宫问题(附代码详解)  BFS算法 算法优化 C++代码 广度优先搜索 第1张

一、题目解读

洛谷1363题要求判断在给定大小的循环迷宫中,从起点出发是否可以通过移动到达多个不同的路径方向。迷宫由字符矩阵表示,'S'为起点,'#'为障碍物,其余为可通行区域。由于迷宫存在循环(即超出边界后从另一侧重新进入),需判断是否存在多条有效路径,避免陷入无限循环。

二、解题思路

核心思路为广度优先搜索BFS)结合虚拟坐标。普通BFS无法处理循环迷宫中的路径重复问题,因此引入虚拟坐标(virtX, virtY)记录每个位置的“相对位移”。每当到达新节点时,若其虚拟坐标与已访问节点不同,说明存在多条路径,即可判定可逃脱。

三、解题步骤

1. 初始化:读取迷宫矩阵,定位起点(startX, startY),初始化队列和访问标记。

2. BFS遍历:从起点开始,依次遍历上、下、左、右四个方向。

3. 边界处理:使用取模运算实现循环边界(如nx = (x + dx + n) % n),确保坐标合法。

4. 虚拟坐标更新:每次移动时,虚拟坐标根据相对位移计算(vx = virtX[x][y] + dx)。

5. 关键判断:若新节点未被访问,标记并加入队列;若已被访问且虚拟坐标不同,直接返回True(可逃脱)。

6. 终止条件:队列为空时仍未找到不同路径,则返回False。

四、代码与注释

#include <iostream>
#include <queue>
#include <cstring>
using namespace std;

const int N = 1505;
char grid[N][N];
bool vis[N][N];
int virtX[N][N], virtY[N][N];
int n, m, startX, startY;
int dirs[4][2] = {{0,1},{0,-1},{1,0},{-1,0}};

bool canEscape() {
    queue<pair<int,int>> q;
    q.push({startX, startY});
    vis[startX][startY] = true;
    virtX[startX][startY] = startX; // 初始化虚拟坐标
    virtY[startX][startY] = startY;

    while (!q.empty()) {
        auto [x,y] = q.front(); q.pop();
        
        for (auto [dx,dy] : dirs) {
            int nx = (x + dx + n) % n; // 循环边界处理
            int ny = (y + dy + m) % m;
            int vx = virtX[x][y] + dx; // 更新虚拟坐标
            int vy = virtY[x][y] + dy;

            if (grid[nx][ny] == '#') continue; // 障碍物跳过

            if (!vis[nx][ny]) { // 未访问节点
                vis[nx][ny] = true;
                virtX[nx][ny] = vx;
                virtY[nx][ny] = vy;
                q.push({nx, ny});
            } 
            else if (virtX[nx][ny]!= vx || virtY[nx][ny]!= vy) { // 关键判断:路径方向不同
                return true; // 存在多条路径,可逃脱
            }
        }
    }
    return false; // 未找到不同路径
}

int main() {
    while (cin >> n >> m) {
        memset(vis, 0, sizeof(vis));
        for (int i = 0; i < n; i++) {
            for (int j = 0; j < m; j++) {
                cin >> grid[i][j];
                if (grid[i][j] == 'S') {
                    startX = i; startY = j;
                }
            }
        }
        cout << (canEscape()? "Yes" : "No") << endl;
    }
    return 0;
}

五、总结

本解法通过虚拟坐标巧妙解决循环迷宫的路径多样性问题,避免了传统BFS在循环结构中的冗余判断。核心在于利用相对位移记录路径方向,通过对比虚拟坐标快速确定是否存在多条有效路径,从而优化算法逻辑。该思路对处理类似循环问题具有通用性,是算法设计与优化的典型范例。


原创内容 转载请注明出处

分享给朋友:

相关文章

2023年GESP五级题「因式分解」洛谷B3871算法解析与代码实现

2023年GESP五级题「因式分解」洛谷B3871算法解析与代码实现

一、题目解读2023年GESP五级题「因式分解」(洛谷B3871)要求将给定的大整数N分解为质因数的乘积形式,并输出每个质因数及其指数。题目考察核心算法为质因数分解,需高效处理大数分解,避免超时。难点...

2024年蓝桥杯国赛A组题 九宫格全解析:基于BFS算法的代码实现与优化

2024年蓝桥杯国赛A组题 九宫格全解析:基于BFS算法的代码实现与优化

一、题目解读2024年蓝桥杯国A的九宫格题目(对应洛谷P10578)要求通过旋转九宫格中的2x2区域,实现从初始状态到目标状态的转换,并计算最小步数。该问题属于经典的图论搜索问题,需要高效的状态转换与...

力扣2771题解析:双数组动态规划求解最长非递减子数组问题

力扣2771题解析:双数组动态规划求解最长非递减子数组问题

一、题目解读力扣2771题要求从两个整数数组nums1和nums2中合并元素,寻找最长非递减子数组的长度。非递减子数组指元素单调递增或相等的连续序列。题目难点在于需同时考虑两个数组的交互关系,找到全局...

【蓝桥杯省赛】2014年A组波动数列题解:动态规划解法与代码解析(C++实现)

【蓝桥杯省赛】2014年A组波动数列题解:动态规划解法与代码解析(C++实现)

一、题目解读“波动数列”是2014年蓝桥杯省赛A组的一道经典题目。题目要求生成一个数列,其前n项的和模n等于给定值s,且每项只能通过加减固定值a、b波动。问题本质是求解满足特定模运算条件的数列组合方案...

力扣2085题解析:统计两个数组中只出现一次的公共单词数目详解

力扣2085题解析:统计两个数组中只出现一次的公共单词数目详解

一、题目解读力扣2085题要求给定两个字符串数组words1和words2,统计两个数组中只出现一次的公共单词的数量。例如,若words1包含["a", "b"...

发表评论

访客

看不清,换一张

◎欢迎参与讨论,请在这里发表您的看法和观点。