【算法】网络图中的dfs

news2025/1/24 14:38:52



快乐的流畅:个人主页


个人专栏:《算法神殿》《数据结构世界》《进击的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.coloradmin.cn/o/1681216.html

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

相关文章

Oracle 自治数据库 Select AI 初体验

这几天有点时间&#xff0c;准备尝试下Oracle Select AI&#xff0c;虽然此功能2023年就已经发布了。 Oracle自治数据库已经集成好了Select AI&#xff0c;本文也是讲的这个。 配置 Select AI 需要以下步骤&#xff1a; 创建ADB申请Cohere/OpenAI免费账号设置ADB测试Select…

【微信小程序开发(从零到一)【婚礼邀请函】制作】——邀请函界面的制作(2)

&#x1f468;‍&#x1f4bb;个人主页&#xff1a;开发者-曼亿点 &#x1f468;‍&#x1f4bb; hallo 欢迎 点赞&#x1f44d; 收藏⭐ 留言&#x1f4dd; 加关注✅! &#x1f468;‍&#x1f4bb; 本文由 曼亿点 原创 &#x1f468;‍&#x1f4bb; 收录于专栏&#xff1a…

开发属于自己的Spring Boot Starter-18

为什么要开发专用的Spring Boot Starter Spring在通常使用时&#xff0c;一般是通过pom.xml文件中引入相关的jar包&#xff0c;然后再通过application.yml文件配置初始化bean的配置&#xff0c;但随着项目越来越复杂或是项目组中的应用数量越来越多&#xff0c;可能会带来几个…

为什么买的蓝牙串口模块不能实现蓝牙键盘给手机文本框或记事本打字或控制手机?

系列文章目录 1.元件基础 2.电路设计 3.PCB设计 4.元件焊接 5.板子调试 6.程序设计 7.算法学习 8.编写exe 9.检测标准 10.项目举例 11.职业规划 文章目录 前言1、原因2、蓝牙键盘制作流程 前言 送给大学毕业后找不到奋斗方向的你&#xff08;每周不定时更新&#xff09; 【…

线程池的一些问题

核心线程数1.最大线程5.队列5.存活时间10s 1.场景一 如果核心线程数.被一直占用得不到释放.新进来1个任务.会怎么样?答: 会在队列中中死等. 只要进来的任务.不超过队列的长度,就会一直挡在队列中死等 package com.lin;import java.util.concurrent.Executors; import java.u…

4.线性代数

深度学习作为一门前沿的、应用广泛的学科&#xff0c;对于数学基础的要求非常高。 线性代数 线性代数在深度学习中扮演着至关重要的角色。它不仅是描述和理解数据的基础工具&#xff0c;也是构建和训练神经网络的核心组件。例如&#xff0c;在深度学习中&#xff0c;我们经常…

ArcGI基本技巧-科研常用OLS, GWR, GTWR模型实现

ArcGI基本技巧-科研常用OLS, GWR, GTWR模型实现 OLS,GWR,GTWR回归模型均可以揭示解释变量对被解释变量的影响且可以进行预测。Ordinary Least Squares (OLS)是最小二乘法&#xff0c;Geographically Weighted Regression (GWR)是地理加权回归&#xff0c;Geographically and T…

Redis-Redis事务

Redis事务 Redis事务简介 Redis事务是一组命令的集合&#xff0c;一个事务中的所有命令都将被序列化&#xff0c;按照一次性、顺序性、排他 性的执行队列系列的命令。Redis单条命令保证原子性&#xff0c;但是事务不保证原子性&#xff0c;且没有回滚。事务中任意命令执行失败…

大模型对数据库运维的赋能:智能运维的新时代

引言随着人工智能技术的飞速发展&#xff0c;大模型作为AI领域的前沿技术&#xff0c;已经开始在数据库运维(DBA)领域展现出其独特的价值。大模型的引入&#xff0c;不仅提升了数据库运维的效率&#xff0c;还极大地改善了运维的质量和智能化水平。本文将深入分析大模型在数据库…

train_gpt2_fp32.cu - main

llm.c/test_gpt2_fp32.cu at master karpathy/llm.c (github.com) 源码 // ---------------------------------------------------------------------------- // main training loop int main(int argc, char *argv[]) {// read in the (optional) command line argumentsco…

【数据结构】排序(直接插入排序,希尔排序)

目录 一、排序的概念 二、常见的排序算法 三、插入排序 1.直接插入排序 1.直接插入排序实现 2.直接插入排序特性及复杂度 2.希尔排序 1.排序思路 2.希尔排序实现 3.希尔排序的特性及复杂度 一、排序的概念 排序&#xff1a;所谓排序&#xff0c;就是使一串记录&#x…

HTML静态网页成品作业(HTML+CSS)——我的家乡江永网页设计制作(1个页面)

&#x1f389;不定期分享源码&#xff0c;关注不丢失哦 文章目录 一、作品介绍二、作品演示三、代码目录四、网站代码HTML部分代码 五、源码获取 一、作品介绍 &#x1f3f7;️本套采用HTMLCSS&#xff0c;未使用Javacsript代码&#xff0c;共有1个页面。 二、作品演示 三、代…

适用于 Mac 的 10 种最佳数据恢复工具优点、缺点

数据丢失很常见&#xff0c;并且可能由于许多不同的原因而发生。这种情况在我和我们团队的其他成员身上发生过很多次&#xff0c;即使我们格外小心我们的个人存储设备。 幸运的是&#xff0c;数据恢复软件在大多数情况下都可以工作。但是&#xff0c;由于数据丢失场景彼此之间…

在UBuntu上安装QT环境

一、UBuntu环境 二、官网下载QT https://download.qt.io/archive/qt/ 安装所需选择版本下载&#xff0c;可以现在windows下载在复制进去 三、安装QT 1、复制到ubuntu 2、打开终端&#xff0c;改变刚下载文件的权限 权限代号 r&#xff1a;读取权限&#xff0c;数字代号为 “…

【Pytorch】9.torch.nn.MaxPool2d

什么是MaxPool2d 是对二维矩阵进行池化层下采样的方法 MaxPool2d的用法 相较于卷积层&#xff0c;多出来的参数为ceil_mode 这个参数代表&#xff0c;如果所剩的部分不够卷积核的大小&#xff0c;要不要进行池化操作 具体代码为 import torch import torchvision from torch …

深度学习之卷积神经网络理论基础

深度学习之卷积神经网络理论基础 卷积层的操作&#xff08;Convolutional layer&#xff09; 在提出卷积层的概念之前首先引入图像识别的特点 图像识别的特点 特征具有局部性&#xff1a;老虎重要特征“王字”仅出现在头部区域特征可能出现在任何位置下采样图像&#xff0c…

laravel 解决composer install报错

laravel 解决报错: Please provide a valid cache path 这是因为laravel的缓存路径没有找到 laravel缓存文件路径是在 config/cache.php中设置&#xff0c;默认存在storage文件夹中 file > [driver > file,path > storage_path(framework/cache/data),], 解决&#x…

快解析Tplink端口映射如何设置

Tplink作为国内知名路由器品牌&#xff0c;有着广泛的用户群体。使用快解析端口映射是实现内网服务器被外网访问必须要做的设置&#xff0c;很多对网络不懂得小白不知道该到哪里去做&#xff0c;下面我就讲解一下tplink路由器如何做端口映射。 1&#xff1a;访问路由器 &#…

HTML静态网页成品作业(HTML+CSS+JS)——在线购物商城网页设计制作(4个页面)

&#x1f389;不定期分享源码&#xff0c;关注不丢失哦 文章目录 一、作品介绍二、作品演示三、代码目录四、网站代码HTML部分代码 五、源码获取 一、作品介绍 &#x1f3f7;️本套采用HTMLCSS&#xff0c;使用Javacsript代码实现图片轮播切换&#xff0c;共有4个页面。 二、…

Elasticsearch的并发控制策略

文章目录 利用external对版本号进行外部控制利用if_seq_no和if_primary_term作为唯一标识来避免版本冲突 ES中的文档是不可变更的。如果你更新一个文档,会将就文档标记为删除,同时增加一个全新的文档。同时文是的version字段加1内部版本控制 If_seq_no If_primary_term 使用外…