【算法】网络图中的dfs



快乐的流畅:个人主页


个人专栏:《算法神殿》《数据结构世界》《进击的C++》

远方有一堆篝火,在为久候之人燃烧!

文章目录

  • 引言
  • 一、单词搜索
  • 二、黄金矿工
  • 三、不同路径 |||
  • 四、图像渲染
  • 五、岛屿数量
  • 六、岛屿的最大面积
  • 七、被围绕的区域
  • 八、太平洋大西洋水流问题
  • 九、扫雷游戏
  • 总结

引言

在二维网络图中的dfs,反而一般不需要画决策树,因为在二维图像中有时候很直观可以看出决策关系,一般为上下左右搜索。

一、单词搜索


细节:

  • dfs函数设置返回值bool,以便及时调整路线
  • 设置向量数组dx,dy
  • 设置bool数组vis,实现剪枝
  • pos设置为函数参数,方便回溯
class Solution
{int dx[4] = {1, -1, 0, 0};int dy[4] = {0, 0, 1, -1};bool vis[7][7];int m, n;
public:bool dfs(vector<vector<char>>& board, int i, int j, string& word, int pos){if(pos == word.size()) return true;vis[i][j] = true;for(int k=0; k<4; ++k){int x = i + dx[k], y = j + dy[k];if(x >= 0 && y >= 0 && x < m && y < n && !vis[x][y] && board[x][y] == word[pos]){if(dfs(board, x, y, word, pos + 1)) return true;}}vis[i][j] = false;return false;}bool exist(vector<vector<char>>& board, string& word){m = board.size(), n = board[0].size();for(int i=0; i<m; ++i){for(int j=0; j<n; ++j){if(board[i][j] == word[0]){if(dfs(board, i, j, word, 1)) return true;}}}return false;}
};

二、黄金矿工


细节:

  • 设置向量数组dx,dy
  • 设置bool数组vis,实现剪枝
  • sum设置为函数参数,方便回溯
class Solution
{int ret = 0;bool vis[16][16];int dx[4] = {1, -1, 0, 0};int dy[4] = {0, 0, 1, -1};int m, n;
public:void dfs(vector<vector<int>>& grid, int i, int j, int sum){vis[i][j] = true;for(int k=0; k<4; ++k){int x = i + dx[k], y = j + dy[k];if(x >= 0 && y >= 0 && x < m && y < n&& !vis[x][y] && grid[x][y]){dfs(grid, x, y, sum + grid[x][y]);}else ret = max(ret, sum);}vis[i][j] = false;}int getMaximumGold(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]){dfs(grid, i, j, grid[i][j]);}}}return ret;}
};

三、不同路径 |||


细节:

  • 设置向量数组dx,dy
  • 设置bool数组vis,实现剪枝
  • path设置为函数参数,方便回溯
class Solution
{int ret = 0;int dx[4] = {1, -1, 0, 0};int dy[4] = {0, 0, 1, -1};bool vis[20][20];int m, n, count = 0;
public:void dfs(vector<vector<int>>& grid, int i, int j, int path){if(grid[i][j] == 2){if(path + count == m * n) ++ret;return;}vis[i][j] = true;for(int k=0; k<4; ++k){int x = i + dx[k], y = j + dy[k];if(x >= 0 && y >= 0 && x < m && y < n&& !vis[x][y] && grid[x][y] != -1){dfs(grid, x, y, path + 1);}}vis[i][j] = false;}int uniquePathsIII(vector<vector<int>>& grid){m = grid.size(), n = grid[0].size();int si, sj;for(int i=0; i<m; ++i){for(int j=0; j<n; ++j){if(grid[i][j] == -1) ++count;else if(grid[i][j] == 1) {si = i, sj = j;}}}dfs(grid, si, sj, 1);return ret;}
};

  • 本题开始往后,是floodfill算法的练习
  • floodfill算法,本质就是寻找连通块
  • 同时floodfill算法没有回溯

四、图像渲染



细节:

  • 设置向量数组dx,dy
  • 记录baseColor, newColor
class Solution
{int dx[4] = {1, -1, 0, 0};int dy[4] = {0, 0, 1, -1};int baseColor, newColor;int m, n;
public:void dfs(vector<vector<int>>& image, int i, int j){image[i][j] = newColor;for(int k=0; k<4; ++k){int x = i + dx[k], y = j + dy[k];if(x >= 0 && y >= 0 && x < m && y < n && image[x][y] == baseColor){dfs(image, x, y);}}}vector<vector<int>> floodFill(vector<vector<int>>& image, int sr, int sc, int color){if(image[sr][sc] == color) return image;baseColor = image[sr][sc], newColor = color;m = image.size(), n = image[0].size();dfs(image, sr, sc);return image;}
};

五、岛屿数量


细节:

  • 设置向量数组dx,dy
  • 设置bool数组vis,实现剪枝
class Solution
{int ret;bool vis[301][301];int dx[4] = {1, -1, 0, 0};int dy[4] = {0, 0, 1, -1};int m, n;
public:void dfs(vector<vector<char>>& grid, int i, int j){vis[i][j] = true;for(int k=0; k<4; ++k){int x = i + dx[k], y = j + dy[k];if(x >= 0 && y >= 0 && x < m && y < n&& !vis[x][y] && grid[x][y] == '1'){dfs(grid, x, y);}}}int numIslands(vector<vector<char>>& grid){m = grid.size(), n = grid[0].size();for(int i=0; i<m; ++i){for(int j=0; j<n; ++j){if(!vis[i][j] && grid[i][j] == '1'){dfs(grid, i, j);++ret;}}}return ret;}
};

六、岛屿的最大面积



细节:

  • 设置向量数组dx,dy
  • 设置bool数组vis,实现剪枝
class Solution
{int ret, sum;vector<vector<bool>> vis;int dx[4] = {1, -1, 0, 0};int dy[4] = {0, 0, 1, -1};int m, n;
public:void dfs(vector<vector<int>>& grid, int i, int j){++sum;vis[i][j] = true;for(int k=0; k<4; ++k){int x = i + dx[k], y = j + dy[k];if(x >= 0 && y >= 0 && x < m && y < n&& !vis[x][y] && grid[x][y] == 1){dfs(grid, x, y);}else ret = max(ret, sum);}}int maxAreaOfIsland(vector<vector<int>>& grid){m = grid.size(), n = grid[0].size();vis.resize(m, vector<bool>(n));for(int i=0; i<m; ++i){for(int j=0; j<n; ++j){if(!vis[i][j] && grid[i][j] == 1){sum = 0;dfs(grid, i, j);}}}return ret;}
};

七、被围绕的区域


细节:

  • 正难则反,将边界上及其相连的‘O’先全部标记起来,最后遍历矩阵,将未被标记的‘O’改成‘X’
  • 设置向量数组dx,dy
  • 设置bool数组vis,实现剪枝
class Solution
{vector<vector<bool>> vis;int dx[4] = {1, -1, 0, 0};int dy[4] = {0, 0, 1, -1};int m, n;
public:void dfs(vector<vector<char>>& board, int i, int j){vis[i][j] = true;for(int k=0; k<4; ++k){int x = i + dx[k], y = j + dy[k];if(x >= 0 && y >= 0 && x < m && y < n&& !vis[x][y] && board[x][y] == 'O'){dfs(board, x, y);}}}void solve(vector<vector<char>>& board){m = board.size(), n = board[0].size();vis.resize(m, vector<bool>(n));for(int i=0; i<m; ++i){if(board[i][0] == 'O') dfs(board, i, 0);if(board[i][n-1] == 'O') dfs(board, i, n-1);}for(int j=0; j<n; ++j){if(board[0][j] == 'O') dfs(board, 0, j);if(board[m-1][j] == 'O') dfs(board, m-1, j);}for(int i=0; i<m; ++i){for(int j=0; j<n; ++j){if(!vis[i][j] && board[i][j] == 'O'){board[i][j] = 'X';}}}}
};

八、太平洋大西洋水流问题




思路:正难则反,水往高处流。

  • 利用两个标记数组,分别记录太平洋和大西洋的水可以流到的区域,找出标记数组重叠的部分即可。
  • 为了只用写一份dfs函数,将vis标记数组以参数的形式传递
  • 设置向量数组dx,dy
class Solution
{int dx[4] = {1, -1, 0, 0};int dy[4] = {0, 0, 1, -1};int m, n;
public:void dfs(vector<vector<int>>& heights, int i, int j, vector<vector<bool>>& vis){vis[i][j] = true;for(int k=0; k<4; ++k){int x = i + dx[k], y = j + dy[k];if(x >= 0 && y >= 0 && x < m && y < n&& !vis[x][y] && heights[x][y] >= heights[i][j])//正难则反,水往高处流{dfs(heights, x, y, vis);}}}vector<vector<int>> pacificAtlantic(vector<vector<int>>& heights){m = heights.size(), n = heights[0].size();vector<vector<bool>> vis1(m, vector<bool>(n));vector<vector<bool>> vis2(m, vector<bool>(n));for(int i=0; i<m; ++i){if(!vis1[i][0]) dfs(heights, i, 0, vis1);if(!vis2[i][n-1]) dfs(heights, i, n-1, vis2);}for(int j=0; j<n; ++j){if(!vis1[0][j]) dfs(heights, 0, j, vis1);if(!vis2[m-1][j]) dfs(heights, m-1, j, vis2);}vector<vector<int>> ret;for(int i=0; i<m; ++i){for(int j=0; j<n; ++j){if(vis1[i][j] && vis2[i][j]){ret.push_back({i, j});}}}return ret;}
};

九、扫雷游戏



细节:本题实际上是一道模拟题,关键是理解题意。

  • 点击位置是雷,直接改变返回
  • 不是雷,则进入dfs函数递归
  • 对于当前格子,先计算周围8个格子中雷的数量
    • 如果有雷,将当前格子改为雷的数量,返回
    • 如果无雷,将当前格子改为挖出的空方块,继续递归
  • 递归的时候,要进行8个方向的搜索,所以向量数组要存储8个方向
class Solution
{bool vis[51][51];int dx[8] = {1, 1, 1, 0, 0, -1, -1, -1};int dy[8] = {1, 0, -1, 1, -1, 1, 0, -1};int m, n;
public:void dfs(vector<vector<char>>& board, int i, int j){if(board[i][j] == 'M') return;int count = 0;for(int k=0; k<8; ++k){int x = i + dx[k], y = j + dy[k];if(x >= 0 && y >= 0 && x < m && y < n && board[x][y] == 'M'){++count;}}if(count){board[i][j] = count + '0';return;}else board[i][j] = 'B';vis[i][j] = true;for(int k=0; k<8; ++k){int x = i + dx[k], y = j + dy[k];if(x >= 0 && y >= 0 && x < m && y < n && !vis[x][y]){dfs(board, x, y);}}}vector<vector<char>> updateBoard(vector<vector<char>>& board, vector<int>& click){int ci = click[0], cj = click[1];if(board[ci][cj] == 'M'){board[ci][cj] = 'X';return board;}m = board.size(), n = board[0].size();dfs(board, ci, cj);return board;}
};

总结

网络图中的dfs,常用的搜索技巧,是创建向量数组dx,dy,方便简洁地用循环遍历。


真诚点赞,手有余香

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

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

相关文章

机器学习之sklearn基础教程(第二篇:数据预处理与特征工程)

机器学习之sklearn基础教程&#xff08;第二篇&#xff1a;数据预处理与特征工程&#xff09; 1. 数据预处理 数据预处理是机器学习中非常重要的一步&#xff0c;它包括对原始数据进行清洗、变换和归一化等操作&#xff0c;以使数据更适合用于机器学习模型的训练和预测。 以下…

冲!哪怕公域拓展流量超卷,数字化转型营销也勇往直前!

在这个数字时代&#xff0c;公域拓展流量的竞争已经激烈到令人咋舌的程度&#xff01;然而&#xff0c;开利网络蚓链数字化转型营销解决方案经过上千家客户实践告诉我们&#xff0c;即使面对如此残酷的局面&#xff0c;我们也必须勇敢地去面对&#xff0c;利用想得到的合规合法…

三磷酸腺苷(ATP)制备方法众多 主要应用于生化研究以及医药领域

三磷酸腺苷&#xff08;ATP&#xff09;制备方法众多 主要应用于生化研究以及医药领域 三磷酸腺苷&#xff08;ATP&#xff09;又称腺嘌呤核苷三磷酸、腺苷三磷酸&#xff0c;化学式为C10H16N5O13P3&#xff0c;是一种高能磷酸化合物。腺苷三磷酸外观呈白色粉末&#xff0c;无特…

2025秋招Java还是c++?

一、我的编程经 说说我的编程经历&#xff0c;在C和Java之间我经历了几个阶段&#xff1a; 大学期间&#xff0c;我浅尝辄止地学习了一段时间的Java&#xff0c;但后来放弃了&#xff0c;开始学习C/C。本科毕业后&#xff0c;我选择攻读硕士学位&#xff0c;并一直专注于C的学…

集成了Gemini的Android Studio,如虎添翼

今天将Android Studio升级到最新版&#xff08;Jellyfish&#xff09;。发现在new features中有一条&#xff1a; Code suggestions with Gemini in Android Studio 打开路径为&#xff1a; View > Tool Windows > Gemini 支持多国语言&#xff0c;英文、中文都能正确理解…

盘点Lombok的几个骚操作,你绝对没用过

本文不讨论对错&#xff0c;只讲骚操作。 有的方法看看就好&#xff0c;知道可以这么用&#xff0c;但是否应用到实际开发中&#xff0c;那就仁者见仁&#xff0c;智者见智了。 一万个读者就会有一万个哈姆雷特&#xff0c;希望这篇文章能够给您带来一些思考。 耐心看完&…

PPT为何无法复制粘贴?附解决办法!

PPT文件里的内容无法复制&#xff0c;或者复制后无法粘贴&#xff0c;这是怎么回事呢&#xff1f; 这种情况&#xff0c;一般是因为PPT被设置了保护&#xff0c;设置了以“只读方式”打开&#xff0c;就无法进行复制粘贴了。PPT的“只读方式”不同&#xff0c;解决方法也不同&…

STM32 HAL TM1637使用

TM1637属于一种带键盘扫描接口的LED&#xff08;发光二极管显示器&#xff09;驱动控制专用电路。 本文主要使用MCU是STM32 &#xff0c;CubeMXKeil5进行开发&#xff0c;使用HAL库 简介&#xff1a;TM1637可以带动16个按键以及做数码管驱动 TM1637.C #include "TM163…

Java入门基础学习笔记25——死循环和循环嵌套

死循环&#xff1a; 可以一直执行下去的一种循环&#xff0c;如果没有干预不会停下来。 死循环的写法&#xff1a; 例&#xff1a; package cn.ensource.loop;public class EndLessLoopDemo5 {public static void main(String[] args) {// 目标&#xff1b;掌握死循环的写法w…

力扣127.单词接龙讲解

距离上一次刷题已经过去了.........嗯............我数一一下............整整十天&#xff0c;今天再来解一道算法题 由于这段时间准备简历&#xff0c;没咋写博客。。今天回来了&#xff01;&#xff01;&#xff01;&#xff01;&#xff01;&#xff01;&#xff01;&…

C++14 新特性:函数返回值类型推导

C11 的特性介绍暂时告一段落&#xff0c;从今天起&#xff0c;我继续介绍 C14 引入的新特性。 C14 进一步增强了 C11 的特性&#xff0c;其中一个改进是对函数返回值类型的自动推导能力的扩展。在 C14 中&#xff0c;编译器可以根据函数返回语句推导出函数的返回类型。 函数返…

【React】如何让函数式组件也能使用state——useState(Hooks)

React的函数式组件不同于类式组件&#xff0c;函数式组件没有自己的 this&#xff0c;看似没有操作state的能力 但是React官方提供了一个Hooks叫useState&#xff0c;它解决了函数式组件和类式组件的差异&#xff0c;让函数式组件拥有了类式组件所拥有的 state &#xff0c;同时…

在win10折腾Flowise:部署和尝试

Flowise 是一种低代码/无代码拖放工具&#xff0c;旨在让人们轻松可视化和构建 LLM 应用程序。 本地部署 操作系统&#xff1a; win10 由于网络、操作系统等各种未知问题&#xff0c;使用npm install -g flowise的方式&#xff0c;尝试了很多次&#xff0c;都没有部署成功&am…

McCabe度量法

McCabe度量法&#xff0c;又称为环路度量&#xff08;Cyclomatic Complexity&#xff09;或循环复杂度&#xff0c;是由Thomas J. McCabe Sr.在1976年提出的一种用于软件工程中的程序复杂性度量方法。这种方法基于程序的控制流图&#xff08;Control Flow Graph, CFG&#xff0…

Visual C++界面开发组件Xtreme Toolkit Pro v24测试版发布——完全支持SVG

Codejock软件公司的Xtreme Toolkit Pro是屡获殊荣的VC界面库&#xff0c;是MFC开发中最全面界面控件套包&#xff0c;它提供了Windows开发所需要的11种主流的Visual C MFC控件&#xff0c;包括Command Bars、Controls、Chart Pro、Calendar、Docking Pane、Property Grid、Repo…

【Daily Code】1953. 你可以工作的最大周数1974. 使用特殊打字机键入单词的最少时间

Problem: 1953. 你可以工作的最大周数 Code class Solution { public:long long numberOfWeeks(vector<int>& milestones) {// 自己想的思路是每次取出那个剩余时间最多的任务来做&#xff08;但是注意不能连着两次都取到同一个任务来做&#xff09;&#xff1b;然后…

震惊!三张图搞定企业数字化转型?开利蚓链就是这么简单!

企业数字化转型&#xff0c;听起来似乎很复杂&#xff0c;让人望而却步&#xff1f;别急&#xff01;开利蚓链数字化生态解决方案告诉你&#xff0c;只需三张图&#xff0c;就能轻松搞定开局&#xff01;一张组织目标图&#xff0c;一张市场路径图&#xff0c;一张权益分配图&a…

WindoWS内核函数 - 字符串复制

DDK提供针对ANSI_STRING字符串和UNICODE_STRING字符串的复制字符串命令&#xff0c;分别是&#xff1a; ANSI_STRING 字符串复制函数&#xff1a; VOID NTAPI RtlCopyString(IN OUT PSTRING DestinationString,IN const STRING * SourceString); // DestinationString: 目的字…

位图和布隆过滤器:位图

在《unordered_map 和 unordered_set》 中提到过&#xff1a; 哈希是一种思想&#xff0c;通过哈希函数将数据转化为一个或多个整型 —— 映射关系&#xff1b;通过这种映射关系&#xff0c;可以做到以 O(1) 的时间复杂度查找数据。 本文即将介绍的 位图 和 布隆过滤器 就是两个…

MySQL数据表的操作

数据表的专业术语 在MySQL数据库管理系统中,具体的数据都是被存储到数据库的多个数据表(table)中,数据库的表格跟excel的表格类似,都是由行(row)和列(column)组成,每一列都称为一个字段(field),列名称为字段名,每一行都称为记录(不包含头),单个单元格成为属性…