【4.3】图搜索算法-DFS和BFS解被围绕的区域

news2024/11/15 10:26:16

一、题目

        给定一个二维的矩阵,包含 ' X ' ' O ' 字母 O )。 找到所有被 ' X ' 围绕的区域,并将这些区域里所有的 ' O ' ' X ' 填充。
示例 :
X X X X
X O O X
X X O X
X O X X
运行你的函数后,矩阵变为:
X X X X
X X X X
X X X X
X O X X
解释:
        被 围 绕 的 区 间 不 会 存 在 于 边 界 上 , 换 句 话 说 , 任 何 边 界 上 的 ' O ' 都 不 会 被 填 充 为 'X' 。 任 何不在边界上,或不与边界上的 ' O ' 相连的 ' O ' 最终都会被填充为 'X'。如果两个元素在水平 或垂直方向相邻,则称它们是“相连”的。

二、解题思路

DFS方式解决:

        题目要求我们将被X包围的O区域替换为X。为了判断O是否被X包围,我们可以采用一种间接的方法。假设矩阵的四周都是X,那么矩阵中任何O必定是被X包围的。如下

        如果矩阵的四周只要有一个是O,那么和这个O直接相邻(仅指上下左右,斜对角不算)的O都不可能被X包围。如下

        因此,一种较为简便的判断方法是检查矩阵的四周是否存在O。若存在O,则表明该O及其直接相邻的O(仅限上下左右,不包括斜对角)无法被X包围,因此不能被替换为X。我们可以先将这些O标记为大写的A(或其他非X和O的字符),然后继续检查其上下左右是否有O,若有,同样标记为A。

最终,矩阵中可能出现三种状态:X、A和O。
- 对于X,保持不变。
- 对于O,说明它们是被X包围的,需要将其替换为X。
- 对于A,说明它们无法被X包围,需将其还原为O。

BFS方式解决:

        DFS是沿着一个方向一直走下去,BFS是先遍历四周的,然后再往外扩散,如下图所示

        原理还是一样的,从矩阵的四周开始,找到一个O之后,把它变为A,然后把他的四周在
遍历一遍,如果有O就加入到队列中,然后继续遍历队列中的元素。

三、代码实现

DFS实现代码:

#include <iostream>
#include <vector>

using namespace std;

void dfs(int i, int j, vector<vector<char>>& board) {
    // 边界条件判断,首先不能跑到矩阵的外边
    if (i < 0 || i >= board.size() || j < 0 || j >= board[0].size())
        return;
    // 如果当前位置不是O,就不用再判断了
    if (board[i][j] != 'O')
        return;
    // 如果当前位置是O,先把他变为'A',然后往他的上下左右4个方向开始递归计算。
    board[i][j] = 'A';
    dfs(i - 1, j, board); // 上
    dfs(i + 1, j, board); // 下
    dfs(i, j - 1, board); // 左
    dfs(i, j + 1, board); // 右
}

void solve(vector<vector<char>>& board) {
    // 边界条件判断
    if (board.empty() || board[0].empty())
        return;

    int rows = board.size();
    int cols = board[0].size();

    // 从矩阵的四周开始判断,也就是矩阵的4条边上有O的地方开始遍历
    for (int i = 0; i < rows; i++) {
        for (int j = 0; j < cols; j++) {
            if (i == 0 || i == rows - 1 || j == 0 || j == cols - 1) {
                if (board[i][j] == 'O')
                    dfs(i, j, board);
            }
        }
    }

    // 重新复原
    for (int i = 0; i < rows; i++) {
        for (int j = 0; j < cols; j++) {
            // 把矩阵中是'A'的还变为O,其他的都变成X
            if (board[i][j] == 'A')
                board[i][j] = 'O';
            else
                board[i][j] = 'X';
        }
    }
}

int main() {
    vector<vector<char>> board = {
        {'X', 'X', 'X', 'X'},
        {'X', 'O', 'O', 'X'},
        {'X', 'X', 'O', 'X'},
        {'X', 'O', 'X', 'X'}
    };

    solve(board);

    // 输出结果
    for (const auto& row : board) {
        for (char c : row) {
            cout << c << " ";
        }
        cout << endl;
    }

    return 0;
}

BFS实现代码:

#include <iostream>
#include <vector>
#include <queue>

using namespace std;

void bfs(int i, int j, vector<vector<char>>& board) {
    queue<int> queue;
    // 把当前位置变为A
    board[i][j] = 'A';
    // 把当前的坐标加入到队列中
    queue.push(i);
    queue.push(j);

    vector<vector<int>> direction = {{-1, 0}, {1, 0}, {0, 1}, {0, -1}};

    while (!queue.empty()) {
        // 坐标出队
        int queueI = queue.front(); queue.pop();
        int queueJ = queue.front(); queue.pop();

        // 沿着当前位置(queueI,queueJ)的上下左右四个方向查找
        for (int k = 0; k < 4; k++) {
            int x = direction[k][0] + queueI;
            int y = direction[k][1] + queueJ;

            // 边界条件判断,首先不能跑到矩阵的外边
            if (x < 0 || x >= board.size() || y < 0 || y >= board[0].size())
                continue;

            // 如果当前位置不是O,就不用再判断了
            if (board[x][y] != 'O')
                continue;

            // 否则就把他变为A
            board[x][y] = 'A';

            // 然后再把这个位置的坐标存放到队列中
            queue.push(x);
            queue.push(y);
        }
    }
}

void solve(vector<vector<char>>& board) {
    // 边界条件判断
    if (board.empty() || board[0].empty())
        return;

    int rows = board.size();
    int columns = board[0].size();

    // 从矩阵的四周开始判断,也就是矩阵的4条边上有O的地方开始遍历
    for (int i = 0; i < rows; i++) {
        for (int j = 0; j < columns; j++) {
            if (i == 0 || i == rows - 1 || j == 0 || j == columns - 1) {
                if (board[i][j] == 'O')
                    bfs(i, j, board);
            }
        }
    }

    // 重新复原
    for (int i = 0; i < rows; i++) {
        for (int j = 0; j < columns; j++) {
            // 把矩阵中是'A'的还变为O,其他的都变成X
            if (board[i][j] == 'A')
                board[i][j] = 'O';
            else
                board[i][j] = 'X';
        }
    }
}

int main() {
    vector<vector<char>> board = {
        {'X', 'X', 'X', 'X'},
        {'X', 'O', 'O', 'X'},
        {'X', 'X', 'O', 'X'},
        {'X', 'O', 'X', 'X'}
    };

    solve(board);

    // 输出结果
    for (const auto& row : board) {
        for (char c : row) {
            cout << c << " ";
        }
        cout << endl;
    }

    return 0;
}

        为了找到被X包围的区域,最简单的方法是从矩阵的四周开始查找。如果四周存在O,那么这些O及其直接相邻的O(仅限上下左右,不包括斜对角)必定无法被X包围。我们可以先将这些O标记为大写的A(或其他非X和O的字符),然后继续检查其相邻的O,同样标记为A。最终,剩下的未被标记为A的O必定是被X包围的。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2149987.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

uniapp H5 打开地图 并选中标记点

uniapp H5 打开地图 并选中标记点 先上代码 //打开地图 显示景区位置openMap() {// 支付宝// #ifdef MP-ALIPAYmy.openLocation({longitude: Number(this.detailObj.longitude), // 经度latitude: Number(this.detailObj.latitude), // 纬度name: this.detailObj.scenicName, …

C++速通LeetCode中等第10题-轮转数组(四种方法)

方法一&#xff1a;巧用deque双向队列容器 class Solution { public:void rotate(vector<int>& nums, int k) {deque<int> q;int tmp;if(nums.size() > 1){for(auto num:nums) q.push_back(num);for(int i 0;i < k;i){tmp q.back();q.pop_back();q.pu…

dgl库安装

此篇文章继续上一篇pytorch已经安装成功的情况 &#xff08;python3.9&#xff0c;pytorch2.2.2&#xff0c;cuda11.8&#xff09; 上一篇pytorch安装教学链接 选择与之匹配的版本 输入下方代码进行测试 import dgl.data dataset dgl.data.CoraGraphDataset() print(‘Numb…

24 小时不关机的挂机云电脑,还能这么玩?

云电脑技术为我们提供了无限可能。特别是对于游戏爱好者&#xff0c;挂机云电脑不仅解决了传统电脑的局限性&#xff0c;还带来了更为便利的游戏体验。除此之外云电脑还有什么其他玩法呢&#xff1f; 01 挂机云电脑的优势 首先要知道&#xff0c;什么是挂机云电脑&#xff1f…

局域网变压器市场价值

2024 年全球局域网变压器市场价值为 3.056 亿美元&#xff0c;预计到 2030 年将达到 4.426 亿美元&#xff0c;2024-2030 年的复合年增长率为 5.4%。 局域网变压器市场包括用于改变电信号电压或格式的产品&#xff0c;以改善和简化局域网 (LAN) 上的数据传输。这些变压器对于保…

【JavaScript】数据结构之链表(双指针、滑动窗口)

什么是链表&#xff1f; 多个元素存储的列表链表中的元素在内存中不是顺序存储的&#xff0c;而是通过“next”指针联系在一起的&#xff0c;这个“next”可以自定义。JS中的原型链原理就是链表结构&#xff0c;是通过__proto__指针联系在一起的。 双指针形式 对撞指针&am…

分布式事务一致性:本地消息表设计与实践

概念 本地消息表是一种常见的解决分布式事务问题的方法。其核心思想是将分布式事务拆分成本地事务来处理&#xff0c;通过消息队列来保证各个本地事务的最终一致性。 实现步骤 创建本地消息表&#xff1a;在数据库中创建一个本地消息表&#xff0c;用于存储待发送的消息以及消…

【图像检索】基于灰度共生矩的纹理图像检索,matlab实现

博主简介&#xff1a;matlab图像代码项目合作&#xff08;扣扣&#xff1a;3249726188&#xff09; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 本次案例是基于灰度共生矩的纹理图像检索&#xff0c;用matlab实现。 一、案例背景和算法介绍 …

从“群聊”到“一单到底”,天润融通工单系统助力品牌服务升级

“您好&#xff0c;我在xx店买的酸奶出现了质量问题&#xff0c;怎么处理&#xff1f;” “你们xx门店的服务态度怎么那么差啊&#xff0c;我要投诉&#xff01;” “您好&#xff0c;xx店的微波炉总是坏的&#xff0c;店员根本不管&#xff01;” 这些耳熟能详的抱怨&#…

【qt】一个WPS项目了解qt界面设计的基本套路

项目功能演示: 放心食用!最后有完整代码. 超级详细,期待您的一个点赞❥(^_-) 一览全局: WPS项目目录 一.创建项目二.导入资源三.ui设计四.字号选择框初始化五.滚动条初始化六.添加自定义文本类七.初始化action状态八.新建文档九.打开文件十.保存与另存为十一.打印/打印预览十…

MySQL高阶1867-最大数量高于平均水平的订单

目录 题目 准备数据 分析数据 题目 您正在运行一个电子商务网站&#xff0c;该网站正在寻找不平衡的订单。不平衡订单的订单最大数量严格大于每个订单&#xff08;包括订单本身&#xff09;的平均数量。 订单的平均数量计算为&#xff08;订单中所有产品的总数量&#xff…

visionpro脚本

visionproToolBlock的脚本的优先级优于工具连线的优先级&#xff0c;一般是照着脚本的执行顺序进行执行对应的工具&#xff0c;最常用的是C#的高级脚本&#xff0c;C#的脚本如下分为5部分。 第一部分&#xff1a;主要是一些库的引用&#xff0c;对于有些类型不知道库的时候&…

14_Python面向对象

面向过程与面向对象 在编程范式&#xff08;programming paradigms&#xff09;中&#xff0c;面向过程&#xff08;Procedural Programming&#xff09;和面向对象&#xff08;Object-Oriented Programming&#xff0c;简称OOP&#xff09;是两种主要的编程风格。 Python是一…

【医学半监督】置信度指导遮蔽学习的半监督医学图像分割

摘要: 半监督学习(Semi-supervised learning)旨在利用少数标记数据和多数未标记数据训练出高性能模型。现有方法大多采用预测任务机制,在一致性或伪标签的约束下获得精确的分割图,但该机制通常无法克服确认偏差。针对这一问题,本文提出了一种用于半监督医学图像分割的新…

(十六)Ubuntu 20.04 下搭建PX4+MATLAB 仿真环境(HITL)

在文章&#xff08;十五&#xff09;Ubuntu 20.04 下搭建PX4MATLAB 仿真环境我们学习了如何配置仿真环境&#xff0c;在本节&#xff0c;主要进行HITL的仿真环境搭建。 根据&#xff08;十五&#xff09;Ubuntu 20.04 下搭建PX4MATLAB 仿真环境完成配置到如下界面&#xff1a;…

志邦家居CIO吴俊涛谈转型:天润融通如何赋能家居行业未来

根据国家统计局、住建部等各部门综合数据显示&#xff0c;2024年国内泛家居全渠道销售额在预计将超过4.7万亿元&#xff0c;并且在存量房需求释放与智能家居品类创新的推动下&#xff0c;预计2027年将突破5.3万亿元&#xff0c;展现出强劲的增长弹性。 然而&#xff0c;家居行…

【matlab】将程序打包为exe文件(matlab r2023a为例)

文章目录 一、安装运行时环境1.1 安装1.2 简介 二、打包三、打包文件为什么很大 一、安装运行时环境 使用 Application Compiler 来将程序打包为exe&#xff0c;相当于你使用C编译器把C语言编译成可执行程序。 在matlab菜单栏–App下面可以看到Application Compiler。 或者在…

mybatisplus逻辑删除

逻辑删除配置 mybatis-plus:global-config:db-config:logic-delete-field: deletedlogic-not-delete-value:0logic-delete-value:1 查询语句也会自动加上where isdeleted0

FedOV

3 FEDOV: ONE-SHOT FEDERATED OPEN-SET VOTING FRAMEWORK 3.1 PROBLEM STATEMENT 假设有个客户端及其本地数据集。我们的目标是在服务器的帮助下&#xff0c;在不交换原始数据的情况下&#xff0c;训练一个优秀的机器学习模型 。此外&#xff0c;每个客户端只允许与服务器进行…

Linux 删除文件不释放空间问题处理

背景&#xff1a; 服务器磁盘空间已经达到100%&#xff0c;删除存放日志路径下的文件后&#xff0c;发现空间并未释放&#xff01; 原因&#xff1a;在linux系统中&#xff0c;通过rm删除文件将会从文件系统的文件夹结构上解除链接(unlink)然后删除&#xff0c;然而假设文件是被…