DFS:深搜+回溯+剪枝解决矩阵搜索问题

news2025/1/15 23:02:10

                                               创作不易,感谢三连!! 

一、N皇后

. - 力扣(LeetCode)

class Solution {
public:
    vector<vector<string>> ret;
    vector<string> path;
    bool checkcol[9];
    bool checkdig1[18];
    bool checkdig2[18];
    int n;
    vector<vector<string>> solveNQueens(int _n) 
    {
        n=_n;
        path.resize(n);
        for(int i=0;i<n;++i)  path[i].append(n,'.');//先全部初始化成.
         dfs(0);
         return ret;
    }

    void dfs(int row)
    {
        if(row==n) {ret.push_back(path);return;}
        for(int col=0;col<n;++col)//枚举每一行的每个元素
        {
            if(checkcol[col]==false&&checkdig1[n+row-col]==false&&checkdig2[row+col]==false)//n+row-col防止越界
            {
               path[row][col]='Q';
               checkcol[col]=checkdig1[n+row-col]=checkdig2[row+col]=true;
                dfs(row+1);
                //恢复现场
               path[row][col]='.';
               checkcol[col]=checkdig1[n+row-col]=checkdig2[row+col]=false;
            }
        }
    }
};

二、有效的数独

. - 力扣(LeetCode)

class Solution {
public:
    bool checkrow[9][10];
    bool checkcol[9][10];
    bool checkgrid[3][3][10];
    bool isValidSudoku(vector<vector<char>>& board) 
    {
         for(int row=0;row<9;++row)
         {
            for(int col=0;col<9;++col)
            {
                if(board[row][col]!='.')
                {
                    int num=board[row][col]-'0';
                    if(checkrow[row][num]||checkcol[col][num]||checkgrid[row/3][col/3][num]) return false;
                    checkrow[row][num]=checkcol[col][num]=checkgrid[row/3][col/3][num]=true;
                }
            }
         }
         return true;
    }
};

三、解数独

. - 力扣(LeetCode)

class Solution {
public:
    bool checkrow[9][10];
    bool checkcol[9][10];
    bool checkgrid[3][3][10];
    void solveSudoku(vector<vector<char>>& board) 
    {
        //初始化
       for(int row=0;row<9;++row)
         for(int col=0;col<9;++col)
         {
            if(board[row][col]!='.')
            {
                int num=board[row][col]-'0';
                checkrow[row][num]=checkcol[col][num]=checkgrid[row/3][col/3][num]=true;
            }
         }
        dfs(board);
    }
        bool dfs(vector<vector<char>> &board)//bool用来告诉上一层决策是正确的
         {
           for(int row=0;row<9;++row)
            for(int col=0;col<9;++col)
         {
            if(board[row][col]=='.')
            {
              //开始尝试填数
              for(int num=1;num<=9;++num)
              {
                if(!checkrow[row][num]&&!checkcol[col][num]&&!checkgrid[row/3][col/3][num])
                {
                    //说明能填,就填上
                    board[row][col]=num+'0';
                    checkrow[row][num]=checkcol[col][num]=checkgrid[row/3][col/3][num]=true;
                    if(dfs(board)) return true;//去下一个位置填,如果填成功了,返回true
                    //恢复现场
                    board[row][col]='.';
                    checkrow[row][num]=checkcol[col][num]=checkgrid[row/3][col/3][num]=false;
                }
              }
              return false;//1-9没有一个数能填,说明决策错误
            }
         }
            return true;//安全地填完了,返回true
         }
};

四、单词搜索

. - 力扣(LeetCode)

class Solution {
public:
    bool check[6][6];//用来标记选过的位置
    int m,n;
    vector<vector<char>> board;
    string word;
    bool exist(vector<vector<char>>& _board, string _word) 
    {
        board=_board;
        word=_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])
             {
                check[i][j]=true;
                if(dfs(i,j,1))  return true;
                check[i][j]=false;
             }
          }
          return false;
    }
    //用向量的方式来定义
     int dx[4]={0,0,-1,1};
     int dy[4]={1,-1,0,0}; //就可以将4个方向改变成一个for循环
    bool dfs(int i,int j,int pos)
    {
        if(pos==word.size())  return true;
        for(int k=0;k<4;++k)
        {
           int x=i+dx[k],y=j+dy[k];
           if(x>=0&&x<m&&y>=0&&y<n&&check[x][y]==false&&board[x][y]==word[pos])
           {
               check[x][y]=true;
               if(dfs(x,y,pos+1)) return true;
               check[x][y]=false;
           }
        }
        return false;//如果四个方向都找不到,说明确实没有可填的数,直接返回
    }
};

五、黄金旷工

. - 力扣(LeetCode)

class Solution {
public:
    int ret=0;
    bool check[15][15];
    int m,n;
    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])
            {
                check[i][j]=true;
                dfs(grid,i,j,grid[i][j]);
                check[i][j]=false;
            }
          }
          return ret;
     }
      //用向量的方式来定义
     int dx[4]={0,0,-1,1};
     int dy[4]={1,-1,0,0}; //就可以将4个方向改变成一个for循环
     void dfs(vector<vector<int>>& grid,int i,int j,int count)
     {
        for(int k=0;k<4;++k)
        {
            int x=i+dx[k],y=j+dy[k];
            if(x>=0&&x<m&&y>=0&&y<n&&!check[x][y]&&grid[x][y])
            {
                check[x][y]=true;
                dfs(grid,x,y,count+grid[x][y]);
                check[x][y]=false;
            }
        }
        ret=max(count,ret);
        //for循环结束,确实没得填了,更新
     }
};

六、不同路径III

. - 力扣(LeetCode)

class Solution {
public:
    int ret;
    bool check[20][20];//用来标记
    int m,n,step;//step用来统计可以走的方格个数
    int uniquePathsIII(vector<vector<int>>& grid) 
    {
        ret=0;
        m=grid.size();
        n=grid[0].size();
        step=0;
        int bx=0,by=0;//记录起点
        //先找起点
        for(int i=0;i<m;++i)
          for(int j=0;j<n;++j)
            {
                if(grid[i][j]==0) ++step;
                else if(grid[i][j]==1) 
                {
                    bx=i;
                    by=j;
                }
            }
        step+=2;//把起点和终点算上,最后走到终点的时候就可以返回了
        check[bx][by]=true;
        dfs(grid,bx,by,1);
        return ret;
    }
    int dx[4]={0,0,-1,1};
    int dy[4]={1,-1,0,0}; //就可以将4个方向改变成一个for循环
    void dfs(vector<vector<int>>& grid,int i,int j,int count)
    {
        if(grid[i][j]==2&&count==step) {++ret;return;}
        for(int k=0;k<4;++k)
        {
            int x=i+dx[k],y=j+dy[k];
            if(x>=0&&x<m&&y>=0&&y<n&&!check[x][y]&&grid[x][y]!=-1)
            {
                check[i][j]=true;
                dfs(grid,x,y,count+1);
                check[i][j]=false;
            }
        }
    }
};

七、小总结

1、矩阵搜索问题经常要用到向量,也就是我们可以通过dx和dy来帮助我们定义方向

2、矩阵搜索要确保走过的位置不再走过,所以此时有两个策略:

(1)标记数组,比较常用

(2)修改原矩阵的内容,但是这样做的话要我们要确保最后能够把它复原 

3、dfs的返回值不一定是void,如果该题目并不只是完全地去统计,而是涉及到我们做出的选择可能会错误的时候,这个时候我们就需要通过bool类型的返回值来帮助我们判断当前的填法是否正确。比如解数独和单词搜索问题

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

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

相关文章

Chat-REC: Towards Interactive and Explainable LLMs-Augmented Recommender System

1、动机 推荐系统被应用于推荐服务&#xff0c;提高人们的生活质量&#xff0c;但仍存在一些问题。缺少交互性、可解释性&#xff0c;缺乏反馈机制&#xff0c;以及冷启动和跨域推荐。 Chat-Rec 将用户画像和历史交互转换为 Prompt&#xff0c;有效地学习用户的偏好&#xff…

Chapter 1 - 9. Introduction to Congestion in Storage Networks

Terminology iSCSI uses the terminology of initiator (or iSCSI client) and target (or iSCSI server). NVMe/TCP uses the terminology of host and controller respectively. iSCSI 使用的术语是启动程序(或 iSCSI 客户端)和目标程序(或 iSCSI 服务器)。NVMe/TCP 分别…

GIS水文分析填充伪洼地学习

1 基本操作 洼地是指流域内被较高高程所包围的局部区域&#xff1b; 分为自然洼地和伪洼地&#xff1b; 自然洼地是自然界实际存在的洼地&#xff1b; 在 DEM 数据中&#xff0c;由于数据处理的误差和不合适的插值方法所产生的洼地&#xff0c;称为伪洼地&#xff1b; DEM 数据…

Day80:服务攻防-中间件安全HW2023-WPS分析WeblogicJettyJenkinsCVE

目录 中间件-Jetty-CVE&信息泄漏 CVE-2021-34429(信息泄露) CVE-2021-28169(信息泄露) 中间件-Jenkins-CVE&RCE执行 cve_2017_1000353 CVE-2018-1000861 cve_2019_1003000 中间件-Weblogic-CVE&反序列化&RCE 应用金山WPS-HW2023-RCE&复现&上线…

win10 安装kubectl,配置config连接k8s集群

安装kubectl 按照官方文档安装&#xff1a;https://kubernetes.io/docs/tasks/tools/install-kubectl-windows/ curl安装 &#xff08;1&#xff09;下载curl安装压缩包: curl for Windows &#xff08;2&#xff09;配置环境变量&#xff1a; 用户变量&#xff1a; Path变…

LeetCode:331. 验证二叉树的前序序列化(模拟 Java)

目录 331. 验证二叉树的前序序列化 题目描述&#xff1a; 实现代码与解析&#xff1a; 模拟 原理思路&#xff1a; 331. 验证二叉树的前序序列化 题目描述&#xff1a; 序列化二叉树的一种方法是使用 前序遍历 。当我们遇到一个非空节点时&#xff0c;我们可以记录下这个节…

Samba 总是需要输入网络凭证

输入网络凭证&#xff1a; 用户名是 cat /etc/samba/smb.conf&#xff0c;查看 valid users mxw 为用户名。而不是其他账号名或者用户名&#xff0c;更不是登录计算机时的计算机名&#xff1b; 密码是 需要记住安装samba服务器时&#xff0c;自己设置的password&#xff1…

zdpcss_transparent_animation_login:使用纯HTML+CSS+JS开发支持设置主题和带动画的科技风登录界面

废话不多说&#xff0c;先上图&#xff0c;有图有真相&#xff1a; 在左下角有一排颜色&#xff0c;点击可以设置主题色&#xff1a; 比如&#xff0c;我这里点击了橙色&#xff0c;登录界面就变成了如下样子&#xff1a; 另外&#xff0c;在输入账号和密码的时候&#x…

设计模式——工厂模式01

工厂模式 定义&#xff1a;工厂模式是创建子类实例化对象的一种方式&#xff0c;屏蔽了创造工厂的内部细节。把创建对象与使用对象进行拆分&#xff0c;满足单一职责。如果需要向工厂中添加新商品&#xff0c; 只需要扩展子类再重写其工厂方法&#xff0c;满足开闭原则。 设计…

STM32-05基于HAL库(CubeMX+MDK+Proteus)串行通信案例(中断方式接收命令)

文章目录 一、功能需求分析二、Proteus绘制电路原理图三、STMCubeMX 配置引脚及模式&#xff0c;生成代码四、MDK打开生成项目&#xff0c;编写HAL库的功能代码五、运行仿真程序&#xff0c;调试代码 一、功能需求分析 在中断机制实现按键检测的案例之后&#xff0c;我们介绍串…

【数据结构】复杂度(长期维护)

本篇博客主要是浅谈数据结构概念及时间复杂度&#xff0c;并做长期的维护更新&#xff0c;有需要借鉴即可。 复杂度目录 一、初识数据结构1.基础概念2.如何学好数据结构 二、复杂度1.复杂度2.时间复杂度①有限数的时间复杂度②函数的时间复杂度③二分查找时间复杂度④递归拓展练…

1.k8s架构

k8s集群架构 一个Kubernetes集群至少包含一个控制平面(control plane)&#xff0c;以及一个或多个工作节点(worker node)。控制平面(Control Plane) : 控制平面负责管理工作节点和维护集群状态。所有任务分配都来自于控制平面。工作节点(Worker Node) : 工作节点负责执行由控制…

Selenium的简单防反爬和浏览器配置

# Selenium的简单使用&#xff1a;https://zhuanlan.zhihu.com/p/557463669 # 防反爬参考&#xff1a;https://blog.csdn.net/weixin_51368459/article/details/125462178 from selenium import webdriver from selenium.webdriver.edge.options import Options# 设置浏览器驱动…

Linux初学(十四)LampLnmp

一、简介 LAMP和LNMP是两种常见的web服务器组合。具体如下&#xff1a; LAMP&#xff1a;LAMP代表的是Linux&#xff08;操作系统&#xff09; Apache&#xff08;HTTP服务器&#xff09; MySQL&#xff08;数据库&#xff09; PHP&#xff08;编程语言&#xff09;。这个组合被…

基于Spring Boot的职称评审管理系统

基于Spring Boot的职称评审管理系统 开发语言&#xff1a;Java框架&#xff1a;springbootJDK版本&#xff1a;JDK1.8数据库工具&#xff1a;Navicat11开发软件&#xff1a;eclipse/myeclipse/idea 部分系统展示 前台首页界面 用户注册登录界面 管理员登录界面 个人中心界面…

【Canvas技法】图解绘制圆弧的重要函数 arc(x,y,r,startAngle,endAngle,clockWise)

【一图释疑】 【绘制上图用代码】 <!DOCTYPE html> <html lang"utf-8"> <meta http-equiv"Content-Type" content"text/html; charsetutf-8"/> <head><title>Html5/Canvas中绘制圆弧的重要函数 arc(x,y,r,startA…

Datacom HCIP笔记-路由策略与路由控制 之一

1、流量可达性控制的2种手段 对流量下手&#xff0c;拒绝流量通过 对路由下手&#xff0c;过滤掉可达的路由信息 Filter-PolicyRIP&#xff0c;OSPF&#xff0c;ISIS&#xff0c;BGP协议都可以使用filter-policy对路由进行过滤。 对协议接收的路由进行过滤&#xff1a;filter-p…

【Qt 学习笔记】Qt 开发环境的搭建 | Qt 安装教程

博客主页&#xff1a;Duck Bro 博客主页系列专栏&#xff1a;Qt 专栏关注博主&#xff0c;后期持续更新系列文章如果有错误感谢请大家批评指出&#xff0c;及时修改感谢大家点赞&#x1f44d;收藏⭐评论✍ Qt 开发环境的搭建 | Qt 安装教程 文章编号&#xff1a;Qt 学习笔记 /…

Calico IPIP和BGP TOR的数据包走向

IPIP Mesh全网互联 文字描述 APOD eth0 10.7.75.132 -----> APOD 网关 -----> A宿主机 cali76174826315网卡 -----> Atunl0 10.7.75.128 封装 ----> Aeth0 10.120.181.20 -----> 通过网关 10.120.181.254 -----> 下一跳 BNODE eth0 10.120.179.8 解封装 --…

一个线程池的理解

最近看到一个线程池&#xff0c;写的实在太好&#xff0c;于是想深入理解一下。原始代码出处&#xff1a;GitHub - Ahajha/CTPL: Modern and efficient C Thread Pool Library 由于平时的工程一般只支持到C11,而拿到的代码应该是在C20下才能编译通过&#xff0c;因此也做了一些…