二道经典OJ题带你入门回溯剪枝算法

风起于青萍之末

浪成于微澜之间


🎥个人主页

🔥个人专栏

🎥前期回顾-环形链表


目录

 回溯算法的简介

N皇后问题

思路

代码测试

N皇后 

思路

判断一竖列是否有皇后

判断对角线是否有皇后

代码测试

 回溯算法的简介

回溯是递归的副产品,只要有递归就会有回溯 所以回溯法也经常和DFS混在一起

回溯的介绍:在搜索解空间时会采用 尝试 与 回退 的策略

回溯算法实际上一个 类似枚举的搜索 尝试过程,主要是在搜索尝试过程中寻找问题的解,当发现已不满足求解条件时,就 回溯 返回,尝试别的路径。回溯法是一种深度优先搜索,按选优条件向前搜索,以达到目标。但当探索到某一步时,发现原先选择并不优或达不到目标,就退回一步重新选择,这种走不通就退回再走的技术为回溯法,而满足回溯条件的某个状态的点称为 回溯点 

剪枝的介绍:

回溯法的基本行为是 搜索,搜索过程使用 剪枝 函数来为了避免无效的搜索

(1)使用约束函数,剪去不满足约束条件的路径

(2)使用限界函数,剪去不能得到最优解的路径

DFS的介绍:

DFS是一种遍历或搜索图、树等数据结构的算法,当然这个图、树未必要存储下来(隐式处理就是回溯法)常见的是通过某种关系构造出的搜索树,搜索树一般是排列型搜索树子集型搜索树

排列型就是每次枚举选哪个

子集型就是对于每一个元素选或不选

DFS 从起始节点开始,沿着一条路径尽可能探入地搜索直到无法继续为止,然后回溯到前一个节点,继续探索其他路径,直到遍历采整个图

DFS 使用栈或递归来管理节点的遍历顺序

N皇后问题

题目链接:N皇后问题


题目描述#

在 N x N 的方格棋盘放置了 N 个皇后,使得它们不相互攻击(即任意 2个皇后不允许处在同一排,同一列,也不允许处在与棋盘边框成 45 度角的斜线上。你的任务是,对于给定的 N,求出有多少种合法的放置方法
输入描述#
输入中有一个正整数 N <= 10,表示棋盘和皇后的数量
输出描述#
为一个正整数,表示对应输入行的皇后的不同放置数量
输入输出样例#

输入

5

输出

10

思路

算法思想:排列型回溯

假设我们是4 x 4棋盘,然后判断皇后在棋盘的攻击范围:

<1>

因为我们是 4x4 的棋盘所以我们要放置4个皇后,所以皇后放置第一行第一列是不行的

<2>

我们发现:

<1>棋盘每行都 必然有且仅有 一个皇后

<2>棋盘的 第一行第一列 放皇后是 不行

<3>每放置一个皇后就将对应的米字型区域设置为 禁区,后面的皇后就不能放在 禁区 里,回溯的时候将 禁区 取消掉

<4>为了正确维护 禁区,不能使用 bool 数组来表示 禁区,需要使用 int 数组,表示这个位置被多少个皇后占用了,当占用数为 0 时表示 禁区 解除

于是我们可以采取逐行放置策略:从第一行开始,在每行放置一个皇后,直至最后一行结束

代码测试

#include<bits/stdc++.h>
using namespace std;
const int N = 10;
int vis[N][N];    //表示多少个皇后被占用了
int n,ans;        //设置全局变量初始化为0
void dfs(int dep) //dep表示当前的搜索深度 
{
  if(dep == n+1)  //从第一行开始,在每行放置一个皇后,直至最后一行结束
  {
    ans++;
    return;
  }
  for(int i = 1;i<=n;i++)
  {
    //当前的位置已经被占用了
    if(vis[dep][i])continue;
    //修改状态,米字形式方阵
    for(int _i = 1;_i<=n;_i++)vis[dep][i]++,vis[_i][i]++;
    for(int _i = dep,j = i;_i>=1&&j>=1;_i--,j--)vis[_i][j]++;
    for(int _i = dep,j = i;_i<=n&&j>=1;_i++,j--)vis[_i][j]++;
    for(int _i = dep,j = i;_i>=1&&j<=n;_i--,j++)vis[_i][j]++;
    for(int _i = dep,j = i;_i<=n&&j<=n;_i++,j++)vis[_i][j]++;
    dfs(dep+1);//搜索下一层
    //恢复(回溯)棋盘,减少位置占用
    for(int _i = 1;_i<=n;_i++)vis[dep][i]--,vis[_i][i]--;
    for(int _i = dep,j = i;_i>=1&&j>=1;_i--,j--)vis[_i][j]--;
    for(int _i = dep,j = i;_i<=n&&j>=1;_i++,j--)vis[_i][j]--;
    for(int _i = dep,j = i;_i>=1&&j<=n;_i--,j++)vis[_i][j]--;
    for(int _i = dep,j = i;_i<=n&&j<=n;_i++,j++)vis[_i][j]--;
  }
}

int main()
{
    cin>>n;
    dfs(1);//从第一个位置开始搜索
    cout<<ans<<endl;
    return 0;
}

N皇后 

题目链接:N皇后


按照国际象棋的规则,皇后可以攻击与之处在同一行或同一列或同一斜线上的棋子。

n 皇后问题 研究的是如何将 n 个皇后放置在 n×n 的棋盘上,并且使皇后彼此之间不能相互攻击。

给你一个整数 n ,返回所有不同的 n 皇后问题 的解决方案。

每一种解法包含一个不同的 n 皇后问题 的棋子放置方案,该方案中 'Q' 和 '.' 分别代表了皇后和空位。

示例 1:

输入:n = 4
输出:[[".Q..","...Q","Q...","..Q."],["..Q.","Q...","...Q",".Q.."]]
解释:如上图所示,4 皇后问题存在两个不同的解法。

示例 2:

输入:n = 1
输出:[["Q"]]

提示:

  • 1 <= n <= 9

思路

回溯+剪枝+坐标系

以下我们用3 x 3的棋盘进行模拟

我们发现:

<1>皇后放在第一行第一列是凑不出 3 的,这种放法是不可行的,所以我们要进行剪枝

<2>棋盘在米字行禁区的需要剪枝

判断一竖列是否有皇后

我们可以定义一个 bool 类型的数组,判断我们这一列是否有皇后

如果为 true 则这一列有皇后,为 false 则这一列没有皇后

判断对角线是否有皇后

我们给将棋盘放在直角坐标系中,对角线的方程为:y = x + b转换一下就是y - x = b

我们发现 (纵坐标 - 横坐标) 是一个常数,于是我们可以定义一个 bool 类型的数组

将这个常数存放在 bool 的数组里面

如果 常数 的坐标是 true 则代表这条对角线有皇后,是 false 则代表这条对角线没有皇后

如果 y - x = b(b是负数),我们可以采用下面这个式子:y - x + n = b + n 整体向上平移

这一侧的对角线已经分析完毕,还有一侧对角线就留给大家去分析


递归深度就是 row 控制棋盘的行,每一层里 for 循环的 col 控制棋盘的列,一行一列,确定了放置皇后的位置

每次都是要从新的一行的起始位置开始搜,所以都是从 0 开始

代码测试

class Solution {
    bool checkCol[10],checkDig1[20],checkDig2[20]; //checkCol一竖列,checkDig1主对角线,checkDig2副对角线
    vector<vector<string>> ret;                    //最终棋盘
    vector<string> path;                           //每个棋盘
    int n;
public:
    vector<vector<string>> solveNQueens(int _n) 
    {
        n = _n;
        path.resize(n);                     //分配空间
        for(int i = 0;i<n;i++)
        path[i].append(n,'.');              //初始化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]&&!checkDig1[row-col+n]&&!checkDig2[row+col])
            {
                path[row][col] = 'Q';
                checkCol[col]=checkDig1[row-col+n]=checkDig2[row+col] = true;//用过了就占用现场
                dfs(row+1);//从下一行开始搜索
            //回溯
                path[row][col] = '.';
                checkCol[col]=checkDig1[row-col+n]=checkDig2[row+col] = false;//不用就收拾现场
            }
        }
    }
};

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

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

相关文章

计算机设计大赛 深度学习+python+opencv实现动物识别 - 图像识别

文章目录 0 前言1 课题背景2 实现效果3 卷积神经网络3.1卷积层3.2 池化层3.3 激活函数&#xff1a;3.4 全连接层3.5 使用tensorflow中keras模块实现卷积神经网络 4 inception_v3网络5 最后 0 前言 &#x1f525; 优质竞赛项目系列&#xff0c;今天要分享的是 &#x1f6a9; *…

5-2、S曲线计算【51单片机+L298N步进电机系列教程】

↑↑↑点击上方【目录】&#xff0c;查看本系列全部文章 摘要&#xff1a;本节介绍S曲线的基本变换&#xff0c;将基本形式的S曲线变换成为任意过两点的S曲线&#xff0c;为后续步进电机S曲线运动提供理论支撑 一.计算目标 ①计算经过任意不同两点的S曲线方程 ②可调节曲线平…

Zephyr NRF7002 实现AppleJuice

BLE的基础知识 ble的信道和BR/EDR的信道是完全不一样的。但是范围是相同的&#xff0c;差不多也都是2.4Ghz的频道。可以简单理解为空中有40个信道0~39信道。两个设备在相同的信道里面可以进行相互通信。 而这些信道SIG又重新编号&#xff1a; 这个编号就是把37 38 39。 3个信道…

「HarmonyOS」CustomDialogController自定义弹窗使用方法

需求背景&#xff1a; 在开发的过程中&#xff0c;总会遇到一些功能需要使用到弹窗进行信息的输入和修改&#xff0c;如用户个人信息的修改&#xff1b;在UI设计上每个App通常都会有各自的样式&#xff0c;而不是使用系统的标准样式&#xff0c;所以通常我们需要进行自定义弹窗…

C++学习Day04之常函数和常对象

目录 一、程序及输出1.1 常函数1.1.1 不能修改对象的成员变量1.1.2 常函数可以被常对象和非常对象调用 1.2 常对象1.2.1 对象的成员变量不能被修改1.2.2 只能调用常函数&#xff0c;不能调用非常函数1.2.3 const_cast 调用非常函数 1.3 常函数中或常对象修改成员变量 二、分析与…

DevOps落地笔记-17|度量指标:寻找真正的好指标?

前面几个课时端到端地介绍了软件开发全生命周期中涉及的最佳实践&#xff0c;经过上面几个步骤&#xff0c;企业在进行 DevOps 转型时技术方面的问题解决了&#xff0c;这个时候我们还缺些什么呢&#xff1f;事实上很多团队和组织在实施 DevOps 时都专注于技术&#xff0c;而忽…

zxxxxczzvdsgbhfdb

欢迎关注博主 Mindtechnist 或加入【Linux C/C/Python社区】一起探讨和分享Linux C/C/Python/Shell编程、机器人技术、机器学习、机器视觉、嵌入式AI相关领域的知识和技术。 磁盘满的本质分析 专栏&#xff1a;《Linux从小白到大神》 | 系统学习Linux开发、VIM/GCC/GDB/Make工具…

【Docker】.NET Core 6.0 webapi 发布上传到Docker Desktop并启动运行访问,接口返回数据乱码解决方法

欢迎来到《小5讲堂》&#xff0c;大家好&#xff0c;我是全栈小5。 这是《Docker容器》系列文章&#xff0c;每篇文章将以博主理解的角度展开讲解&#xff0c; 特别是针对知识点的概念进行叙说&#xff0c;大部分文章将会对这些概念进行实际例子验证&#xff0c;以此达到加深对…

进程控制(Linux)

进程控制 一、进程创建1. 再识fork2. 写时拷贝 二、进程终止前言——查看进程退出码1. 退出情况正常运行&#xff0c;结果不正确异常退出 2. 退出码strerror和errno系统中设置的错误码信息perror异常信息 3. 退出方法exit和_exit 三、进程等待1. 解决等待的三个问题2. 系统调用…

使用pandas将excel转成json格式

1.Excel数据 2.我们想要的JSON格式 {"0": {"raw_data1": "Sam","raw_data2": "Wong","raw_data3": "Good","layer": "12v1"},"1": {"raw_data1": "Lucy…

外汇天眼:大量的平庸操作无济于事,少数的杰出操作改变人生

回顾我们的人生&#xff0c;道路虽然漫长&#xff0c;经历虽然众多&#xff0c;但紧要处其实只有关键的几步。 在关键时刻处理得最好的人就会拥有最成功的事业; 回顾我们所交过的朋友&#xff0c;虽然数量像天上的繁星&#xff0c;但真正对自己的人生有重大影响的&#xff0c;不…

NUUO 网络摄像头命令执行漏洞

一、设备简介 NUUO NVR是中国台湾省NUUO公司旗下的一款网络视频记录器&#xff0c;该设备存在远程命令执行漏洞&#xff0c;攻击者可利用该漏洞执行任意命令&#xff0c;进而获取服务器的权限。 网络视频记录器的CPU为Marvell Kirkwood 88F6281&#xff0c;CPU架构为基于ARMv5…

LLM(大语言模型)——大模型简介

目录 概述 发展历程 大语言模型的概念 LLM的应用和影响 大模型的能力、特点 大模型的能力 涌现能力&#xff08;energent abilities&#xff09; 作为基座模型支持多元应用的能力 支持对话作为统一入口的能力 大模型的特点 常见大模型 闭源LLM&#xff08;未公开源…

GADM 4.1 全球国家行政区划下载

扫描文末二维码&#xff0c;关注微信公众号&#xff1a;ThsPool 后台回复g004&#xff0c;领取最新 GADM 4.1 全球国家行政区划 GADM概述 GADM&#xff0c;全称 Database of Global Administrative Areas&#xff0c;是一个开放获取的全球行政区划数据库&#xff0c;包含各国、…

智慧城市与数字孪生:技术驱动下的城市治理与生活变革

一、引言 随着科技的飞速发展&#xff0c;智慧城市和数字孪生已经成为现代城市发展的重要趋势。它们通过运用先进的信息通信技术&#xff0c;提升了城市的治理效率和居民的生活品质。本文将探讨智慧城市与数字孪生如何共同推动城市治理与生活的变革&#xff0c;以及面临的挑战…

Webpack源码浅析

webpack启动方式 webpack有两种启动方式&#xff1a; 通过webpack-cli脚手架来启动&#xff0c;即可以在Terminal终端直接运行&#xff1b; webpack ./debug/index.js --config ./debug/webpack.config.js通过require(webpack)引入包的方式执行&#xff1b;其实第一种方式最终…

踩坑了,MySQL数据库生成大量奇怪的大文件

作者&#xff1a;田逸&#xff08;formyz&#xff09; 一大早就收到某个数据库服务器磁盘满的报警信息&#xff0c;其中数据盘使用率超过90%&#xff0c;如下图所示。 这是一台刚上线不久的MySQL从库服务器&#xff0c;数据盘的总容量是300G。先登录系统&#xff0c;查看主从同…

一般系统的请求认证授权思路【gateway网关+jwt+redis+请求头httpheader】

gateway&#xff1a;网关&#xff0c;我们都知道网关的作用就是对系统的所有请求&#xff0c;网关都会进行拦截&#xff0c;然后做一些操作&#xff08;例如&#xff1a;设置每个请求的请求头httpHeader&#xff0c;身份认证等等&#xff09;此时一般会使用到网关过滤器&#x…

感悟笔记——2024年2月5日

今日阅读了一篇挺有深度的文章&#xff0c;主要阐述进入职场后的大部分人&#xff0c;是怎么逐渐沦为螺丝钉的?即使起点巨高的优等生&#xff0c;也不可避免。文章指路&#xff1a; 「优等生思维」正在将你变成「螺丝钉」和「老黄牛」从小到大&#xff0c;我一直都是那个「别…

随记-Java项目处理SQL注入问题

现象&#xff1a;http://10.xx.xx.xx:xx/services/xxService 存在SQL注入情况 加固意见&#xff1a; 需要对网站所有参数中提交的数据进行过滤&#xff0c;禁止输入“"、"xor"、"or"、”--“、”#“、”select“、”and“等特殊字符&#xff1b;所有…