BFS:FloodFill算法

2024-06-21 13:04
文章标签 算法 bfs floodfill

本文主要是介绍BFS:FloodFill算法,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

文章目录

  • FloodFill算法简介
  • 1.图像渲染
  • 2.岛屿数量
  • 3.岛屿的最大面积
  • 4.被围绕的区域
  • 总结

在这里插入图片描述

FloodFill算法简介

Flood Fill算法是一种用于确定与某个给定节点相连的区域的算法,常用于计算机图形学和图像处理。该算法可以用于诸如填充多边形、检测连通区域等任务。Flood Fill算法有多种实现方式,其中最常见的是递归方法和使用栈或队列的迭代方法。

基本思想
Flood Fill算法从一个初始像素开始,检查该像素的颜色。如果颜色匹配(即需要填充的颜色),则将其填充为新的颜色,然后对相邻的像素重复这一过程,直到所有相连的匹配像素都被填充为止。

在这里插入图片描述
FloodFill算法也叫洪水灌溉法,上图中0表示岛屿,1表示海洋,如果要我们求岛屿的个数的话就可以用洪水灌溉法则。

在这里插入图片描述

灌溉之后就像上面一样。
接下来,我们来练习几道题熟悉一下FloodFill算法。

1.图像渲染

题目链接
题目:

在这里插入图片描述

样例输入和输出:

在这里插入图片描述

这道题的意思很简单,就是我们固定一个位置,这个位置的坐标是[sr,sc]这个位置周围的和这个这个区块数字相同数都会被变成新的数字。
以上面这个例子为例,初始坐标是中间坐标,那么渲染的区块就是:
在这里插入图片描述
在这里插入图片描述
如果利用FloodFill算法的话,我们按顺序灌溉应该是1->2->3->4。

算法原理:
利用BFS的FloodFill算法,这个算法我们只需要借助队列,每次入队列的时候改变当前节点的值。

代码展示:

class Solution {
public:typedef pair<int,long> PIL;//定义一个方向数组,上下左右四个位置int dx[4]={0,0,1,-1};int dy[4]={1,-1,0,0};vector<vector<int>> floodFill(vector<vector<int>>& image, int sr, int sc, int color) {//标记一下需要修改的像素值int prev=image[sr][sc];int m=image.size();int n=image[0].size();if(prev==color){return image;//处理边界情况}queue<PIL> q;q.push({sr,sc});while(q.size()){auto [a,b]=q.front();q.pop();image[a][b]=color;for(int i=0;i<4;i++){int x=a+dx[i];int y=b+dy[i];if(x>=0&&x<m&&y>=0&&y<n&&image[x][y]==prev){q.push({x,y});}}}return image;}
};

2.岛屿数量

题目链接
题目:

在这里插入图片描述

样例输入和输出:

在这里插入图片描述

我们来看示例1:
在这里插入图片描述
这道题1是岛屿,0是海,然后这个数组的周围默认都是海。

算法原理:
这道题和上道题的思路是一样的,但是还多出来一步,就是当我们利用bfs来遍历数组的时候,假如我们从第一个位置开始遍历,遍历了一遍,记录了一个岛屿,但是我们第二次遍历的时候从第二个位置的1开始遍历,但是第二个位置的1是属于第一个岛屿的,所以这里就会产生重复,解决这种重复问题的办法就是开一个bool类型的vis数组,这个数组的大小和给定的数组的大小是相同的,我们每访问一个岛屿就将这个岛屿上对应的vis变为true,表示我们已经访问过这个节点了,所以这里进行bfs的条件多了一个不仅需要这个节点的值是1,还需要这个节点对应的vis数组是true。

代码展示:

class Solution {
public:typedef pair<int,int> PIL;int dx[4]={0,0,1,-1};int dy[4]={1,-1,0,0};bool vis[301][301];int ret=0;int m,n;void bfs(vector<vector<char>>& grid,int i,int j){queue<PIL> q;q.push({i,j});vis[i][j]=false;while(q.size()){auto [a,b]=q.front();q.pop();for(int k=0;k<4;k++){int x=a+dx[k];int y=b+dy[k];if(x < m && x >= 0 && y >= 0&&y<n&&grid[x][y]=='1'&&vis[x][y]==false){vis[x][y]=true;q.push({x,y});}}}}int numIslands(vector<vector<char>>& grid) {m=grid.size();n=grid[0].size();for(int i=0;i<grid.size();i++){for(int j=0;j<grid[i].size();j++){if(grid[i][j]=='1'&&vis[i][j]==false){bfs(grid,i,j);//将这个陆地标记一下ret++;}}}return ret;}
};

3.岛屿的最大面积

题目链接
题目:

在这里插入图片描述

样例输入和输出:

在这里插入图片描述

这道题的背景和上一道题是一样的,但是这道题不是让我们求岛屿的数量而是让我们求所有岛屿中面积最大的那个岛屿大面积

算法原理:
这道题需要的变量和上道题也是一样的,但是唯一不同的一点是上一道题是void,这道题是int,所以我们需要记录每次BFS的结果,我们用S记录每次BFS的结果,然后每次BFS之后,和前一次求出来的面积进行比较,最后直接返回最大值。

代码展示:

class Solution {
public:typedef pair<int,int> PIL;int dx[4]={0,0,1,-1};int dy[4]={1,-1,0,0};bool vis[51][51];int m,n;int S;int bfs(vector<vector<int>>& grid,int i,int j){int Sum=0;queue<PIL> q;q.push({i,j});Sum++;vis[i][j]=true;while(q.size()){auto [a,b]=q.front();q.pop();for(int k=0;k<4;k++){int x=a+dx[k];int y=b+dy[k];if(x>=0&&x<m&&y>=0&&y<n&&grid[x][y]==1&&vis[x][y]==false){vis[x][y]=true;q.push({x,y});Sum++;}}}return Sum;}int maxAreaOfIsland(vector<vector<int>>& grid) {m=grid.size();n=grid[0].size();for(int i=0;i<m;i++){for(int j=0;j<n;j++){if(grid[i][j]==1&&vis[i][j]==false){int S1=bfs(grid,i,j);if(S<S1){S=S1;}}}}return S;}
};

4.被围绕的区域

题目链接
题目:

在这里插入图片描述

样例输入和输出:

在这里插入图片描述

这道题给出的二维数组中的值只有X和O,这道题的意思就是让我们修改被x包围的O为x,然后边界的联通区域不需要修改。
我们用一个例子来表示上面的题意:
在这里插入图片描述

蓝色区域表示不能修改的边界联通区域,灰色区域表示被X围住的中间的需要修改的联通区域。

算法原理,如果这道题我们直接正面做的话,很难,因为当我们进行BFS的时候,我们并不知道这块区域是边界联通的区域,就像下面这种情况:
在这里插入图片描述
上面这种情况,当我们从第一个位置开始BFS我们到后面才知道这个联通区域是边界区域,但是我们又不能倒过去找,所以我们只能先标记这个边界区域,然后再用一次BFS对可修改区域进行修改,所以这里我们先对边界区域进行遍历,先把边界区域修改为另一个字符,这里我们将这个字符定义为’*'修改了之后,我们只需要对这个二维数组遍历一遍,将O修改为X,将 *修改为O即可。

代码展示:

class Solution {
public:typedef pair<int,int> PII;int m,n;int dx[4]={0,0,1,-1};int dy[4]={1,-1,0,0};void bfs(vector<vector<char>>& board,int i,int j){queue<PII> q;q.push({i,j});board[i][j]='*';while(q.size()){auto [a,b]=q.front();q.pop();for(int k=0;k<4;k++){int x=a+dx[k];int y=b+dy[k];if(x>=0&&x<m&&y>=0&&y<n&&board[x][y]=='O'){q.push({x,y});board[x][y]='*';}}}}void solve(vector<vector<char>>& board) {m=board.size();n=board[0].size();for(int j=0;j<n;j++){if(board[0][j]=='O')bfs(board,0,j);if(board[m-1][j]=='O')bfs(board,m-1,j);}for(int i=0;i<m;i++){if(board[i][0]=='O')bfs(board,i,0);if(board[i][n-1]=='O')bfs(board,i,n-1);}for(int i=0;i<m;i++){for(int j=0;j<n;j++){if(board[i][j]=='O')board[i][j]='X';if(board[i][j]=='*')board[i][j]='O';}}}
};

总结

Flood Fill算法在图像处理和计算机图形学中扮演着重要角色。无论是用于简单的填色任务,还是复杂的区域检测,这一算法都展示了其强大的功能。本文详细介绍了Flood Fill算法的基本思想,并提供了递归和迭代两种实现方式。递归方法虽然简单直观,但在处理较大图像时可能会遇到递归深度的限制;而迭代方法则通过显式管理待填充的像素,克服了这一问题。

通过这两种实现方法的比较,我们不仅了解了Flood Fill算法的原理,也掌握了如何选择合适的实现方式来应对不同的应用场景。希望这篇博客能帮助大家更好地理解和应用Flood Fill算法,在实际项目中解决相关问题。

如果您有任何问题或需要进一步讨论,欢迎在评论区留言。感谢您的阅读!

这篇关于BFS:FloodFill算法的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1081297

相关文章

代码随想录算法训练营:12/60

非科班学习算法day12 | LeetCode150:逆波兰表达式 ,Leetcode239: 滑动窗口最大值  目录 介绍 一、基础概念补充: 1.c++字符串转为数字 1. std::stoi, std::stol, std::stoll, std::stoul, std::stoull(最常用) 2. std::stringstream 3. std::atoi, std

人工智能机器学习算法总结神经网络算法(前向及反向传播)

1.定义,意义和优缺点 定义: 神经网络算法是一种模仿人类大脑神经元之间连接方式的机器学习算法。通过多层神经元的组合和激活函数的非线性转换,神经网络能够学习数据的特征和模式,实现对复杂数据的建模和预测。(我们可以借助人类的神经元模型来更好的帮助我们理解该算法的本质,不过这里需要说明的是,虽然名字是神经网络,并且结构等等也是借鉴了神经网络,但其原型以及算法本质上还和生物层面的神经网络运行原理存在

多源 BFS

例题一 解法(bfs)(多个源头的最短路问题) 算法思路: 对于求的最终结果,我们有两种⽅式: • 第⼀种⽅式:从每⼀个 1 开始,然后通过层序遍历找到离它最近的 0 。 这⼀种⽅式,我们会以所有的 1 起点,来⼀次层序遍历,势必会遍历到很多重复的点。并且如果 矩阵中只有⼀个 0 的话,每⼀次层序遍历都要遍历很多层,时间复

大林 PID 算法

Dahlin PID算法是一种用于控制和调节系统的比例积分延迟算法。以下是一个简单的C语言实现示例: #include <stdio.h>// DALIN PID 结构体定义typedef struct {float SetPoint; // 设定点float Proportion; // 比例float Integral; // 积分float Derivative; // 微分flo

LeetCode 算法:二叉树的中序遍历 c++

原题链接🔗:二叉树的中序遍历 难度:简单⭐️ 题目 给定一个二叉树的根节点 root ,返回 它的 中序 遍历 。 示例 1: 输入:root = [1,null,2,3] 输出:[1,3,2] 示例 2: 输入:root = [] 输出:[] 示例 3: 输入:root = [1] 输出:[1] 提示: 树中节点数目在范围 [0, 100] 内 -100 <= Node.

【Java算法】滑动窗口 下

​ ​    🔥个人主页: 中草药 🔥专栏:【算法工作坊】算法实战揭秘 🦌一.水果成篮 题目链接:904.水果成篮 ​ 算法原理 算法原理是使用“滑动窗口”(Sliding Window)策略,结合哈希表(Map)来高效地统计窗口内不同水果的种类数量。以下是详细分析: 初始化:创建一个空的哈希表 map 用来存储每种水果的数量,初始化左右指针 left

ROS2从入门到精通4-4:局部控制插件开发案例(以PID算法为例)

目录 0 专栏介绍1 控制插件编写模板1.1 构造控制插件类1.2 注册并导出插件1.3 编译与使用插件 2 基于PID的路径跟踪原理3 控制插件开发案例(PID算法)常见问题 0 专栏介绍 本专栏旨在通过对ROS2的系统学习,掌握ROS2底层基本分布式原理,并具有机器人建模和应用ROS2进行实际项目的开发和调试的工程能力。 🚀详情:《ROS2从入门到精通》 1 控制插

算法与数据结构面试宝典——回溯算法详解(C#,C++)

文章目录 1. 回溯算法的定义及应用场景2. 回溯算法的基本思想3. 递推关系式与回溯算法的建立4. 状态转移方法5. 边界条件与结束条件6. 算法的具体实现过程7. 回溯算法在C#,C++中的实际应用案例C#示例C++示例 8. 总结回溯算法的主要特点与应用价值 回溯算法是一种通过尝试各种可能的组合来找到所有解的算法。这种算法通常用于解决组合问题,如排列、组合、棋盘游

【图像识别系统】昆虫识别Python+卷积神经网络算法+人工智能+深度学习+机器学习+TensorFlow+ResNet50

一、介绍 昆虫识别系统,使用Python作为主要开发语言。通过TensorFlow搭建ResNet50卷积神经网络算法(CNN)模型。通过对10种常见的昆虫图片数据集(‘蜜蜂’, ‘甲虫’, ‘蝴蝶’, ‘蝉’, ‘蜻蜓’, ‘蚱蜢’, ‘蛾’, ‘蝎子’, ‘蜗牛’, ‘蜘蛛’)进行训练,得到一个识别精度较高的H5格式模型文件,然后使用Django搭建Web网页端可视化操作界面,实现用户上传一

【数据结构与算法 经典例题】使用队列实现栈(图文详解)

💓 博客主页:倔强的石头的CSDN主页               📝Gitee主页:倔强的石头的gitee主页    ⏩ 文章专栏:《数据结构与算法 经典例题》C语言                                   期待您的关注 ​​ 目录  一、问题描述 二、前置知识 三、解题思路 四、C语言实现代码 🍃队列实现代码: