当前位置:首页 > 洛谷 > 洛谷P1141题解:迷宫连通块问题的深度优先搜索算法与代码解析

洛谷P1141题解:迷宫连通块问题的深度优先搜索算法与代码解析

2天前

洛谷P1141题解:迷宫连通块问题的深度优先搜索算法与代码解析 洛谷题解 深搜 深度优先搜索 队列 队列结构 算法解析 第1张

一、题目解读

洛谷P1141题目要求处理一个由字符构成的迷宫,其中相同字符形成连通块,不同字符构成分隔。题目需统计连通块数量及大小,并支持查询两点是否属于同一连通块。核心在于高效识别并标记迷宫中的连通区域,同时处理边界条件和查询操作。

二、解题思路

采用**深度优先搜索DFS)**策略。首先遍历迷宫,遇到未标记的单元格时启动DFS,将相邻的不同字符单元格合并为同一连通块,并记录块大小。通过方向数组实现四向遍历,利用队列优化搜索过程,确保遍历所有可达区域。最终通过连通块标记数组判断查询点的归属。

三、解题步骤

1. 输入处理:读取迷宫尺寸n×m,外层包裹边界防止越界访问,按行列顺序存储字符。

2. 连通块标记:初始化标记数组为零。遍历每个单元格,若未标记则启动DFS:

    入队当前坐标,标记为当前连通块编号,计数初始化。

    循环队列:取出队头坐标,遍历四向邻点。

    若邻点满足边界、未标记且字符不同,则合并至当前块(标记编号、计数+1、入队)。

3. 查询处理:循环m次,读取查询坐标,直接比较标记数组值判断连通性。

四、代码与注释

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

// 方向数组:上、下、左、右
const int dx[] = {-1, 1, 0, 0};
const int dy[] = {0, 0, -1, 1};

int main() {
    ios::sync_with_stdio(false);
    cin.tie(nullptr); // 加快输入输出速度
    
    int n, m;
    cin >> n >> m; // 迷宫尺寸n×m,查询次数m
    
    // 读取迷宫,注意题目行列从1开始
    vector<vector<char>> grid(n+2, vector<char>(n+2));
    for (int i = 1; i <= n; ++i) {
        for (int j = 1; j <= n; ++j) {
            cin >> grid[i][j];
        }
    }
    
    // 连通块标记和大小统计
    vector<vector<int>> component(n+2, vector<int>(n+2, 0));
    vector<int> component_size(1); // 从1开始计数
    
    int current_component = 0; // 当前连通块编号
    
    for (int i = 1; i <= n; ++i) {
        for (int j = 1; j <= n; ++j) {
            if (component[i][j] == 0) { // 未标记单元格
                current_component++; // 创建新连通块
                queue<pair<int, int>> q; // 队列辅助DFS
                q.push({i, j}); // 起始坐标入队
                component[i][j] = current_component; // 标记
                int size = 1; // 块大小初始化
                
                while (!q.empty()) { // 遍历可达区域
                    auto [x, y] = q.front(); // 取出队头坐标
                    q.pop();
                    
                    for (int k = 0; k < 4; ++k) { // 四向扩展
                        int nx = x + dx[k];
                        int ny = y + dy[k];
                        
                        // 检查边界、未访问且数字相反
                        if (nx >= 1 && nx <= n && ny >= 1 && ny <= n &&
                            component[nx][ny] == 0 && 
                            grid[nx][ny]!= grid[x][y]) {
                            component[nx][ny] = current_component; // 合并标记
                            size++; // 统计块大小
                            q.push({nx, ny}); // 邻点入队
                        }
                    }
                }
                component_size.push_back(size); // 记录块大小
            }
        }
    }
    
   
// 处理查询
    while (m--) {
        int x, y;
        cin >> x >> y;
        cout << component_size[component[x][y]] << "\n";
    }
}

五、总结

本解法通过DFS+队列优化高效处理迷宫连通块问题,核心在于利用方向数组简化遍历逻辑,并通过标记数组避免重复搜索。边界检查和字符差异判断是关键步骤,确保连通块准确划分。此外,预处理块大小数组简化了后续查询复杂度。代码结构清晰,可扩展性强,适用于同类迷宫连通性求解场景。


原创内容 转载请注明出处

分享给朋友:

相关文章

力扣965题深度解析:单值二叉树的判断技巧

力扣965题深度解析:单值二叉树的判断技巧

重新解读题目 判断一棵二叉树是否为“单值二叉树”,即所有节点的值是否完全相同。题目看似简单,实则考验对树结构递归特性的理解。若一棵树的所有节点值相同,其必然满足:根节点与左右子树的值一致,且...

【CSP-S 2019】括号树(洛谷P5658)解题报告:栈+DFS+异或优化详解

【CSP-S 2019】括号树(洛谷P5658)解题报告:栈+DFS+异或优化详解

一、题目解读括号树问题(洛谷P5658)要求处理一个由括号序列转化的树结构:每个节点表示一个括号,'('为子节点,')'为父节点。题目给定一棵n个节点的树,需计算每个节...

洛谷1656题解:基于Tarjan算法求解割边问题(附代码与详细步骤)

洛谷1656题解:基于Tarjan算法求解割边问题(附代码与详细步骤)

一、题目解读洛谷1656题要求在无向图中找出所有割边(即删除后导致图不连通的边)。题目核心在于判断图的连通性,并识别哪些边是“桥”。需理解图论中的连通分量概念,以及如何通过算法高效定位割边。二、解题思...

洛谷P2190题解:铁路售票系统车厢计算(差分数组+前缀和优化)

洛谷P2190题解:铁路售票系统车厢计算(差分数组+前缀和优化)

一、题目解读洛谷P2190题要求解决铁路售票系统中的车厢数量计算问题。题目给定n个车站和m条订票申请,每条申请包含区间[x,y)及乘客数z。需要计算在不超载的情况下(每节车厢最多36人),满足所有乘客...

洛谷2652题解析:同花顺排序问题的动态规划与滑动窗口优化

洛谷2652题解析:同花顺排序问题的动态规划与滑动窗口优化

一、题目解读洛谷2652题要求对一组扑克牌进行排序,目标是找到最少需要调整的次数,使得所有牌形成同花顺。题目中,扑克牌由花色和数字组成,需先按花色排序,再在同花色内按数字排序。核心难点在于如何处理花色...

力扣LCP41题解析:棋盘翻转算法优化与C++深度优先搜索策略

力扣LCP41题解析:棋盘翻转算法优化与C++深度优先搜索策略

一、题目解读力扣LCP41题要求玩家在给定棋盘中,通过翻转单个棋子(将'.'变为'X'),使其周围'X'连锁翻转'O',最终计算最多能翻...

发表评论

访客

看不清,换一张

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