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

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;
    }
};

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

dataphin是什么及其简单使用示例

1.1dataphin是什么&#xff1f; Dataphin是由阿里研发的智能大数据建设平台&#xff0c;提供一站式数据中台&#xff08;大数据平台&#xff09;建设服务。Dataphin通过沙箱&#xff08;项目&#xff09;实现业务及作业资源隔离&#xff0c;运行更快&#xff0c;且数据同步到D…

代码随想录算法训练营第四十八 | ● 121. 买卖股票的最佳时机 ● 122.买卖股票的最佳时机II

121. 买卖股票的最佳时机 买卖股票的最佳时机 视频讲解&#xff1a;https://www.bilibili.com/video/BV1Xe4y1u77q https://programmercarl.com/0121.%E4%B9%B0%E5%8D%96%E8%82%A1%E7%A5%A8%E7%9A%84%E6%9C%80%E4%BD%B3%E6%97%B6%E6%9C%BA.html class Solution { public:int ma…

因你而变 共赴新程 | AidLux全新版本震撼发布!

历经400多个日夜&#xff0c;AidLux 2.0&#xff08;基础版&#xff09;终于要与大家见面了。 开发者们问过无数次&#xff0c;新版本何时发布&#xff0c;期待的功能何时上线……在此&#xff0c;让我先真诚地感谢大家长期以来的期待与关心&#xff01; 一年多以来&#xff…

如何从官网下载 mysql 二进制安装包

一.下载二进行包 1. 官网网址: https://www.mysql.com/ 如图所示进入官网 2. 点击 DOWNLOADS ,进入如下图 在该页面找到 MySQL Community (GPL) Downloads 点进去 如上图页面&#xff0c;找到 MySQL Community Server 在点进去 下载 linux 通用版 点击最下面 Compressed …

服务监控-微服务小白入门(5)

背景 什么是服务监控 监视当前系统应用状态、内存、线程、堆栈、日志等等相关信息&#xff0c;主要目的在服务出现问题或者快要出现问题时能够准确快速地发现以减小影响范围。 为什么要使用服务监控 服务监控在微服务改造过程中的重要性不言而喻&#xff0c;没有强大的监控…

kafka-生产者拦截器(SpringBoot整合Kafka)

文章目录 1、生产者拦截器1.1、创建生产者拦截器1.2、KafkaTemplate配置生产者拦截器1.3、使用Java代码创建主题分区副本1.4、application.yml配置----v1版1.5、屏蔽 kafka debug 日志 logback.xml1.6、引入spring-kafka依赖1.7、控制台日志 1、生产者拦截器 1.1、创建生产者拦…

SkyWalking之P0核心业务场景输出调用链路应用

延伸扩展&#xff1a;XX核心业务场景 路由标签打标、传播、检索 链路标签染色与传播 SW: SkyWalking的简写 用户请求携带HTTP头信息X-sw8-correlation “X-sw8-correlation: key1value1,key2value2,key3value3” 网关侧读取解析HTTP头信息X-sw8-correlation&#xff0c;然后通…

Dokcer 基础使用 (4) 网络管理

文章目录 Docker 网络管理需求Docker 网络架构认识Docker 常见网络类型1. bridge 网络2. host 网络3. container 网络4. none 网络5. overlay 网络 Docker 网路基础指令Docker 网络管理实操 其他相关链接 Docker 基础使用(0&#xff09;基础认识 Docker 基础使用(1&#xff09;…

【HarmonyOS4学习笔记】《HarmonyOS4+NEXT星河版入门到企业级实战教程》课程学习笔记(十三)

课程地址&#xff1a; 黑马程序员HarmonyOS4NEXT星河版入门到企业级实战教程&#xff0c;一套精通鸿蒙应用开发 &#xff08;本篇笔记对应课程第 20 - 21节&#xff09; P20《19.ArkUI-属性动画和显式动画》 本节先来学习属性动画和显式动画&#xff1a; 在代码中定义动画&am…

使用difflib实现文件差异比较用html显示

1.默认方式&#xff0c;其中加入文本过长&#xff0c;需要换行&#xff0c;因此做 contenthtml_output.replace(</style>,table.diff td {word-wrap: break-word;white-space: pre-wrap;max-width: 100%;}</style>)&#xff0c;添加换行操作 ps&#xff1a;当前te…

BGP汇总+认证

一、BGP 的宣告问题 1、在 BGP 协议中每台运行 BGP 的设备上&#xff0c;宣告本地直连路由 2、在 BGP 协议中运行 BGP 协议的设备来宣告.通过 IGP 学习到的&#xff0c;未运行 BGP 协议设备产2、生的路由&#xff1b; 在 BGP 协议中宣告本地路由表中路由条目时,将携带本地到达这…

PostgreSQL基础(九):PostgreSQL的事务介绍

文章目录 PostgreSQL的事务介绍 一、什么是ACID&#xff08;常识&#xff09; 二、事务的基本使用 三、保存点&#xff08;了解&#xff09; PostgreSQL的事务介绍 一、什么是ACID&#xff08;常识&#xff09; 在日常操作中&#xff0c;对于一组相关操作&#xff0c;通常…

视频大模型 Vidu 支持音视频合成;字节跳动推出语音生成模型 Seed-TTS 丨 RTE 开发者日报 Vol.221

开发者朋友们大家好&#xff1a; 这里是 「RTE 开发者日报」 &#xff0c;每天和大家一起看新闻、聊八卦。我们的社区编辑团队会整理分享 RTE&#xff08;Real-Time Engagement&#xff09; 领域内「有话题的新闻」、「有态度的观点」、「有意思的数据」、「有思考的文章」、「…

鸿蒙全栈开发-浅谈鸿蒙~线程模型

前言 如果你现在正巧在找工作&#xff0c;或者琢磨着换个职业跑道&#xff0c;鸿蒙开发绝对值得你考虑一下。 为啥&#xff1f;理由很简单&#xff1a; 市场需求大&#xff1a;鸿蒙生态还在持续扩张&#xff0c;应用开发、系统优化、技术支持等岗位需求旺盛&#xff0c;找工作…

三分搜索峰值

问题 现在有一个数组&#xff0c;显示递增&#xff0c;后是递减&#xff0c;如何找到它的峰值&#xff1f; 思路 可以利用分治的思想&#xff0c;向二分查找一样&#xff0c;每次将要查询的区域分成若干个区域&#xff0c;根据区域的特殊点的值淘汰一些区域&#xff0c;缩小…

基于Python的Selenium详细教程

一、PyCharm安装配置Selenium 本文使用环境&#xff1a;windows11、Python 3.10.5、PyCharm 2022.1.3、Selenium 4.3.0 需要你懂的技术&#xff1a;Python、HTML、CSS、JavaScript 1.Seleium安装&#xff1a; 在PyCharm终端或window命令窗口输入以下命令 #查看已安装的Pytho…

硬件产品经理

边端协调管理平台 主页一&#xff1a;模型管理1.1 边侧模型管理 二&#xff1a;配置管理2.1 终端软件配置管理 三&#xff1a;设备管理3.1 区域位置管理3.2 工控机管理&#xff08;其实就是围绕授权&#xff09;3.3 生产设备管理3.4 设备运行管理 四&#xff1a;数据服务4.1 实…

ISP:企业数字化发展的关键推动力

在当今信息化时代&#xff0c;互联网已成为人们生活和工作中不可或缺的一部分。然而&#xff0c;对于很多人来说&#xff0c;ISP这一概念仍显得有些陌生。ISP&#xff0c;即互联网服务提供商&#xff08;Internet Service Provider&#xff09;&#xff0c;是为用户提供互联网接…

【课程总结】Day6(上):机器学习项目实战--外卖点评情感分析预测

机器学习项目实战&#xff1a;外卖点评情感分析预测 项目目的 基于中文外卖评论数据集&#xff0c;通过机器学习算法&#xff0c;对评论内容进行情感预测。 数据集 地址&#xff1a;http://idatascience.cn/dataset-detail?table_id429数据集字段 字段名称字段类型字段说…

package.json中resolutions的使用场景

文章目录 用途配置示例使用方法注意事项和peerDependencies有什么不同peerDependenciesresolutions 总结 ✍创作者&#xff1a;全栈弄潮儿 &#x1f3e1; 个人主页&#xff1a; 全栈弄潮儿的个人主页 &#x1f3d9;️ 个人社区&#xff0c;欢迎你的加入&#xff1a;全栈弄潮儿的…