【回溯算法】N皇后问题·构建多叉决策树,遍历决策节点,做出决策(边),收集答案

news2024/11/18 9:40:40

0、前言

在由树形解空间入手,深入分析回溯、动态规划、分治算法的共同点和不同点这篇博客,其实已经对回溯算法的思想、做题框架做出了详细的阐述。这篇文章我们再从N皇后问题,加深我们对其理解。

这里在简单再次对其进行概述:

回溯算法的核心就是构建和遍历一棵【多叉决策树】

  • 树的节点是一个决策节点,站在一个节点上我们只需要思考三个问题
    1. 当前已经做出的选择:路径
    2. 当前还可以做出哪些选择(选择列表)
    3. 结束条件:到达叶子决策节点,得到一个答案,进行收集
  • 树的边:代表一个决策(选择)

在这里插入图片描述

  • 🪧代码框架:

    result = []
    def backtrack(路径, 选择列表):
        if 满足结束条件:
            result.add(路径)
            return
        
        for 选择 in 选择列表:
            做选择
            backtrack(路径, 选择列表)
            撤销选择
    
  • backtrack函数就相当于游走在这颗多叉决策树上的一个指针,它来遍历决策节点,并且做出决策。进入backtrack函数,就以为着我们进入了一个决策节点,也意味着我们需要思考上面所示的三个问题。

  • 其核心就是 for 循环里面的递归, 在递归调用之前在这个决策节点上「做选择」,在递归调用之后「撤销选择」

一、51.N 皇后

1.1:题目

力扣链接
在这里插入图片描述

1.2:解题思路

  • 分析:这题分析用回溯算法来解其实不难。下棋的棋子该落在哪个位置有多种可能(需要满足限制条件),这个棋盘的每一层就相当于决策多叉树的每一层,我们需要遍历这个决策多叉树,进行所有可能的决策,最终把所有解法收集起来,这就是一个回溯的过程。

  • 实现:分析出来回溯之后,我们核心是需要写出backtrack递归函数,它是实现整个回溯遍历的核心。进入到backtrack函数,就相当于进入到一个决策节点,我们必须思考以下3个问题

    1. 当前已经做出选择的路径:可以用一个棋盘存储:vector <string> board
    2. 选择列表(站在当前决策节点可以做出哪些选择):可以用row来表示,在board的第row行的每一列是否放置皇后,有n列那么当前该层(行)就有n个选择
    3. 终止条件:当row<=n时,说明0~n-1行已经全部放置好了函数,当前这个路径(board棋盘)可以作为一个答案被收集

    注意的是,不是每一列都可以放置皇后,题目中对皇后的放置有限制条件,所有在遍历选择列表时,对选择需要进行决策可行性判断 (也就是剪枝,代表不能做这个选择)。从这点可以看到,⭐如果不了解回溯算法,一开始感觉会执着于这个限制条件,从而不知道如何下手,但是在决策算法里,它只是一个对决策的限制,我们只需要在遍历到这个决策边时,再进行判断(剪枝)即可。
    在这里插入图片描述

1.3:完整代码

class Solution {
private:
    vector<vector<string>> res; //最终答案的收集
    
    /*backtrack函数,相当于游走在这个多叉树每一个决策节点形解空间的一个指针(指向的就是一个决策节点)
    作用是来构建这个决策多叉树、遍历多叉树的边(一个边就代表一个选择)和收集答案
    - 当前路径:board棋盘用来记录当前路径(在小于row行时做出的选择)
    - 选择列表:在board的第row行的每一列是否放置皇后,有n列那么当前该层(行)就有n个选择
    - 结束条件:当row<=n时,说明0~n-1行已经全部放置好了皇后,当前这个路径(board棋盘)可以作为一个答案被收集
    */
    void backtrack(vector<string> board, int row){
        if(row == board.size()){
            res.push_back(board);
            return;
        }

        //进行当前决策节点(这一行)的选择遍历
        int col = board[row].size();
        for (int i = 0; i < col; i++){

            /*********前序位置:做出选择(从当前决策节点到下一个决策节点)**************/
            //剪枝,如果当前选择不合理
            if(!isValid(board, row , i)){
                continue;
            }
            //合理,则做出选择
            board[row][i] = 'Q';

            /********进入下一个决策节点,接着向下遍历*****************************/
            backtrack(board, row+1);

            /*********后序位置,撤销当前选择*******************/
            board[row][i] = '.';
        }
    }

    /*
    剪枝,判断当前(row,col)这个位置放入皇后的话是否合理
    */
    bool isValid(vector<string> &board, int row, int col){
        //判断列
        for(int i =0; i < row; i++){
            if(board[i][col] == 'Q') return false;
        }
        //判断左上方
        for(int i =row-1, j =col-1; i >=  0 && j >= 0; i--, j--){
            if(board[i][j] == 'Q') return false;
        }
        //判断右上方
        for(int i =row-1, j = col+1; i >= 0 && j < board.size(); i--, j++){
            if(board[i][j] == 'Q') return false;
        }
        return true;
    }
public:
    vector<vector<string>> solveNQueens(int n) {
        vector<string> board(n,string(n, '.')); //存储路径
        backtrack(board, 0);
        return res;
    }
};

二、52. N 皇后 II

2.1:题目

力扣链接
在这里插入图片描述

2.2:解题思路

这题解题思路和上面一个一模一样,唯一不同的就是答案收集的变量需要变一下而与!!!之前是存储整个答案,这里的话用一个计数的整形变量ans来存储即可,遍历到底层叶子节点,收集答案ans++即可。

 if(row == board.size() ){
            ans ++;
            return;
        }

2.3:完整代码

class Solution {
public:
    int ans = 0; //在回溯过程中收集和存储最终答案

    /*回溯指针函数backtrack
    - 当前路径:由board来记录’
    - 选择列表:当前第row行的每一列都是可以选择的
    - 结束条件(收集到一个答案): row == board.size()
    */
    void backtrack(vector<string>& board, int row){
        if(row == board.size() ){
            ans ++;
            return;
        }
        
        //下面进行当前决策节点边的遍历(选择列表中做出选择)
        for(int col = 0; col < board.size(); col ++){
            //剪枝,如果当前选择不合法,就不继续遍历该决策子节点
            if(!isValid(board, row , col)){
                continue;
            }
            /***前序位置:表示做出当前边的决策**/
            board[row][col] = 'Q';

            //接着向下遍历子决策节点
            backtrack(board, row + 1);

            /***后序位置,撤销当前决策**********/
            board[row][col] = '.';
        }
    }

    bool isValid(vector<string>& board, int row, int col){
        //首先判断列
        for(int i = row -1; i >=0; i --){
            if(board[i][col] == 'Q') return false;
        }
        //判断左上方
        for(int i = row-1, j = col-1; i >=0 && j >= 0; i--, j--){
            if(board[i][j] == 'Q') return false;
        }
        //判断右上方
        for(int i = row-1, j = col +1; i >=0 && j <board.size(); i--, j++){
            if(board[i][j] == 'Q') return false;
        }
        return true;
    }

    int totalNQueens(int n) {
        vector<string> board(n, string(n, '.')); //存储当前路径
        backtrack(board, 0);
        return ans;
    }
};

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

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

相关文章

3、前端本地环境搭建

前端本地环境搭建 安装node [node下载地址] https://nodejs.org/en/download/prebuilt-installer 选择LTS的版本进行下载 下载后直接双击点击&#xff0c;选择自己想要安装到的目录一直点下一步即可&#xff08;建议不要安装到c盘&#xff09; 安装完成后配置环境变量&am…

NLP课程笔记-基于transformers的自然语言处理入门

NLP课程笔记-基于transformers的自然语言处理入门 项目地址2.1 图解attention2.1.1 Seq2seq框架2.1.2 Seq2seq细节2.1.3 Attention1) 基于RNN的seq2seq模型的问题2)基于Attention seq2seq方案 2.2 图解transformer2.2.1 transformer宏观结构单层编码器单层解码器 2.2.2 transfo…

揭秘FL Studio21.2最新官方免费下载中文破解版!

在音乐创作中&#xff0c;一个优秀的宿主软件是必不可少的。而FL Studio 21.2中文破解汉化免费版&#xff0c;作为一款功能强大、易于上手的宿主软件&#xff0c;已经成为越来越多音乐制作者的首选。那么&#xff0c;它究竟有何魅力呢&#xff1f;下面就让我们一起来了解一下。…

.Net Core 8.0 IIS部署遇到奇怪的部分接口报404的问题解决

本地运行没问题&#xff0c;部署到IIS后&#xff0c;部分接口报404&#xff0c;其它接口都正常。 经和群里讨论&#xff0c;大概意思是接口返回数据比较大的时候&#xff0c;就会出现这个问题。 查看事件查看器&#xff0c;发现应该是数据过大时使用了临时文件夹&#xff0c;…

CondaSSLError: OpenSSL appears to be unavailable on this machine.

conda create -n x1 python3.7报错 PS C:\Users\Richardo.M.Song\Desktop\lele_seg\x1> conda create -n x1 python3.7 Collecting package metadata (current_repodata.json): failed CondaSSLError: OpenSSL appears to be unavailable on this machine. OpenSSL is requ…

【TB作品】MSP430G2553单片机,MSP430 单片机读取 SHT30 传感器并显示数据

使用 MSP430 单片机读取 SHT30 传感器并显示数据 作品功能 本文介绍了如何使用 MSP430 单片机读取 SHT30 温湿度传感器的数据&#xff0c;并通过 OLED 屏幕显示实时的温度和湿度信息。通过此项目&#xff0c;您将学习如何配置 MSP430 的 I2C 接口、读取 SHT30 传感器的数据以…

求助!什么软件可以人声分离?手机上可以进行人声分离操作吗?

在数字时代&#xff0c;音频处理变得越来越重要&#xff0c;而人声分离技术则是其中的一项关键技术。很多人可能都有过这样的疑问&#xff1a;什么软件可以实现人声分离&#xff1f;手机上能否进行人声分离操作&#xff1f;今天&#xff0c;我们就来为大家解答这些问题&#xf…

封装组件库仿elementui<1>

目录 type属性 引入字体图标 button的点击事件 disabled属性 methods:{//点击事件是外部注册的handleClick(e){this.$emit(click,e)//通知父组件点击了&#xff0c;点了按钮&#xff0c;触发外界的click&#xff1f;传参为事件对象//向父组件派发了click事件} }, type属性…

揭露:抖音外卖区域代理骗局真相,绝不可错过!

自2023年11月23日抖音发布清退服务商的公告后&#xff0c;由官方认证的抖音外卖平台全国代理正式成为历史&#xff0c;而后&#xff0c;抖音外卖平台区域代理接棒&#xff0c;帮助抖音开拓本地生活市场。在此背景下&#xff0c;抖音外卖平台区域代理的申请人数与日俱增&#xf…

Frida 学习之 messages

目录 一、消息发送 二、环境准备 三、从目标进程中发消息 四、在目标进程中接收消息 五、在目标进程中以阻塞方式接收消息 官方链接&#xff1a;Messages | Frida • A world-class dynamic instrumentation toolkit 参考链接&#xff1a;Frida官方手册 - 消息发送_frida…

【Mac】Keyboard Maestro for Mac(键盘大师)软件介绍及安装教程

软件介绍 Keyboard Maestro for mac&#xff08;键盘大师&#xff09;是目前Mac OS平台上功能最为齐全的Mac键盘增强工具&#xff0c;它能将你的Keyboard作用发挥到极致&#xff0c;可以根据命令或计划自动执行简单或复杂的应用程序或网站&#xff0c;文本或图像。使用Keyboar…

mysql 8 linux7,8安装教程

选择自己对应的linux版本 cat /etc/os-release //查看自己linux系统版本 1.mysql下载地址 MySQL :: Download MySQL Community Server (Archived Versions) 拉到下面找到 选择自己linux指定的版本&#xff0c;否则会很麻烦 cat /etc/os-release //查看系统版本 2.查…

matlab模拟太阳耀斑喷发

代码 function simulate_solar_flare% 参数设置gridSize 100; % 网格大小timeSteps 200; % 时间步数dt 0.1; % 时间步长% 初始化网格[X, Y] meshgrid(linspace(-5, 5, gridSize));Z zeros(size(X));% 设置耀斑初始位置和强度flareCenter [0, 0]; % 耀斑中心位置flareRad…

docker基础,docker安装mysql,docker安装Nginx,docker安装mq,docker基础命令

核心功能操作镜像 Docker安装mysql docker run -d --name mysql -p 3306:3306 -e TZAsia/Shanghai -e MYSQL_ROOT_PASSWORDlcl15604007179 mysql docker的基本操作 docker rm 容器名称即可 docker ps 查看当前运行的容器 docker rm 干掉当前容器 docker logs 查看容器命令日…

【MySQL | 第十二篇】重新认识MySQL数据类型

12.理解MySQL数据类型 12.1整数类型 整数类型有五种&#xff1a;tinyint、smallint、mediumint、int、bigint&#xff08;1&#xff0c;2&#xff0c;3&#xff0c;4&#xff0c;8字节&#xff09;&#xff0c;存储范围为 -2^(N-1) 到 2^(N-1)-1所有整数类型默认有符号数&…

【红黑树变色+旋转】

文章目录 一. 红黑树规则二. 情况一叔叔存在且为红情况二.变色旋旋 一. 红黑树规则 对于红黑树&#xff0c;进行变色旋转处理&#xff0c;终究都是为了维持颜色以下几条规则&#xff0c;只有颜色和规则维持住了&#xff0c;红黑树就维持住了最长路径的长度不超过最短路径的两倍…

FastAPI给docs/配置自有域名的静态资源swagger-ui

如果只是要解决docs页面空白的问题&#xff0c;可先看我的这篇博客&#xff1a;FastAPI访问/docs接口文档显示空白、js/css无法加载_fastapi docs打不开-CSDN博客 以下内容适用于需要以自用域名访问swagger-ui的情况&#xff1a; 1. 准备好swagger-ui的链接&#xff0c;如&am…

mysql optimizer_switch : 查询优化器优化策略深入解析

码到三十五 &#xff1a; 个人主页 在 MySQL 数据库中&#xff0c;查询优化器是一个至关重要的组件&#xff0c;它负责确定执行 SQL 查询的最有效方法。为了提供DBA和开发者更多的灵活性和控制权&#xff0c;MySQL 引入了 optimizer_switch 系统变量。这个强大的工具允许用户开…

os和os.path模块

自学python如何成为大佬(目录):https://blog.csdn.net/weixin_67859959/article/details/139049996?spm1001.2014.3001.5501 目录也称文件夹&#xff0c;用于分层保存文件。通过目录可以分门别类地存放文件。我们也可以通过目录快速找到想要的文件。在Python中&#xff0c;并…

领域驱动设计(DDD)深入探究

领域驱动设计&#xff08;DDD&#xff09;深入探究 一、DDD 简介1.1 历史和背景1.2 领域驱动设计的概念1.2 领域驱动设计的核心概念1. 领域&#xff08;Domain&#xff09;2. 子域&#xff08;Subdomain&#xff09;3. 限界上下文&#xff08;Bounded Context&#xff09;4. 实…