回溯算法之N皇后

一   什么是回溯算法

回溯算法(Backtracking Algorithm)是一种用于解决组合优化问题的算法,它通过逐步构建候选解并进行验证,以寻找所有满足特定条件的解。回溯算法通常应用于在给定约束条件下枚举所有可能解的问题,如组合、排列、子集等。

回溯算法的基本思想是通过递归的方式进行搜索,每一步都尝试扩展当前的解,直到找到满足条件的解或者确定无解。在搜索的过程中,如果当前的解不满足约束条件,就会回溯到上一步进行其他选择,继续搜索。

回溯算法的一般步骤如下:

  1. 定义问题的解空间,确定问题的约束条件。
  2. 通过递归的方式搜索解空间,每一步都进行选择,并进行约束条件的检查。
  3. 如果当前的选择满足约束条件,则继续递归地进行下一步选择。
  4. 如果当前的选择不满足约束条件,进行回溯,撤销当前选择,返回上一步继续搜索其他选择。
  5. 当搜索完成后,得到所有满足条件的解。

回溯算法的时间复杂度通常较高,因为它需要枚举所有可能的解。在某些情况下,可以通过剪枝等优化策略来减少搜索空间,提高算法效率。

回溯算法在很多问题中都有应用,例如八皇后问题、0-1背包问题、图的遍历等。它是一种非常经典和常用的算法思想,对于解决组合优化问题具有重要的作用。

通常解该类题目时,我们要确定解的空间,从而很好的利用回溯算法来解决该类题目。


二   何为解空间

      解空间(Solution Space)是指在给定问题的约束条件下,所有可能的解的集合。它包含了问题的所有合法解。

      解空间的具体形式取决于问题的性质和约束条件。对于某些问题,解空间可能是一个有限的集合,例如在数独游戏中,解空间是由符合数独规则的所有数字填充方案组成的集合。而对于其他问题,解空间可能是一个无限的集合,例如在连续优化问题中,解空间是由实数构成的无限维空间。

     解空间是问题求解的关键概念之一。在解决问题时,我们通常需要在解空间中搜索满足特定条件的解。回溯算法、枚举法、剪枝算法等求解方法都是基于对解空间的搜索。

      解空间的大小直接影响了问题的复杂性和求解算法的效率。如果解空间非常大,问题的求解可能会非常困难,需要耗费更多的时间和资源。因此,在实际应用中,优化算法常常通过剪枝、启发式搜索等技术来减小解空间的规模,以提高求解效率。

总之,解空间是问题求解中描述所有可能解的概念,通过搜索解空间,我们可以找到满足问题要求的解或者找到最优解。

对于大多数该类问题的解空间都是树的形式,集合的大小构成了树的宽度,递归的深度构成的树的深度。


三   回溯算法的模板

下面是回溯算法的一般模板:

void backtracking(参数) {if (终止条件) {存放结果;return;}for (选择:本层集合中元素(树中节点孩子的数量就是集合的大小)) {//横向遍历处理节点;//这里一般可能进行剪枝操作backtracking(路径,选择列表); // 递归,纵向遍历回溯,撤销处理结果}
}

这是一个基本的回溯算法模板,其中的关键点包括:

  1. 定义终止条件:当满足终止条件时,表示找到了一个解或者不再需要继续搜索,可以进行相应的操作,如输出结果或返回。

  2. 遍历选择列表:遍历所有可能的选择,通常使用循环结构,对于每个选择,进行相应的操作。

  3. 做出选择:根据当前选择,更新状态或路径,表示对问题的一次选择。

  4. 递归进入下一层决策树:根据当前选择,进入下一层决策树,即进行下一步的选择。

  5. 撤销选择:在回溯到上一层之前,需要撤销当前选择,恢复状态或路径,以便进行下一个选择。

在实际应用中,根据具体问题的不同,模板中的代码需要进行相应的修改和扩展,以适应问题的特点和约束条件。同时,通过剪枝、优化等技巧,可以对模板进行改进,提高算法的效率。

需要注意的是,回溯算法是一种暴力搜索的方法,解空间的规模很大时,可能会导致算法效率低下。因此,在使用回溯算法时,需要根据问题的规模和特点进行合理的优化和剪枝,以提高算法的性能。


四   回溯算法例题之N皇后问题

按照国际象棋的规则,皇后可以攻击与之处在同一行或同一列或同一斜线上的棋子。n 皇后问题 研究的是如何将 n 个皇后放置在 n×n 的棋盘上,并且使皇后彼此之间不能相互攻击。

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

4*4的棋盘摆放结果如下:

解题思路:

  1. 定义一个 N × N 的棋盘,使用一个二维数组或其他数据结构表示。初始化棋盘的所有位置为空。

  2. 从第一行开始,逐行放置皇后。对于每一行,遍历该行的每一个位置,尝试将皇后放置在当前位置。

  3. 在放置皇后之前,检查是否满足以下条件:

    • 当前位置的同一列没有其他皇后。
    • 当前位置的左上方和右上方(对角线)没有其他皇后。
  4. 如果满足上述条件,将皇后放置在当前位置,并将该位置标记为已占用。

  5. 继续递归地处理下一行,重复步骤 3 和步骤 4。

  6. 如果已经放置了 N 个皇后,表示找到了一个可行解,将该解保存起来。

  7. 回溯到上一步,撤销对当前位置的选择,继续尝试下一个位置。

  8. 当所有的位置都尝试完毕或者已经找到了所有的可行解时,算法结束。

  9. 返回所有的可行解。

    我们先以3*3的棋盘来看它的解空间,如图所示:

不难看出解空间对应的是树的结构,我们可以套用模板进行解决:

void Backtrack(char bord[][N],int n,int row){if(row>=n){//递归出口print(bord,n);//如果满足直接打印结果count++;//用来记录解的数量printf("\n");return ;}else{for(int colum=0;colum<n;colum++){//横向遍历if(isselect(bord,row,colum,n)){//如果满足放置条件bord[row][colum] = 'Q';Backtrack(bord,n,row+1);//进行递归,选择下一行的格子bord[row][colum] = '*';//回溯}}}
}

 【完整代码】

#include <stdio.h>
#include <stdbool.h>
#define N 100int count=0;
void print(char bord[][N],int n){for(int i=0;i<n;i++){for(int j=0;j<n;j++){if(bord[i][j] == 'Q'){printf("  Q");}else{printf("  *");} }printf("\n");} 
}bool isselect(char bord[][N], int row, int colum,int n) {for(int j=0;j<row;j++){//判断列if(bord[j][colum]=='Q'){return false;}}for(int i=row,j=colum;i>=0&&j>=0;i--,j--){//判断左上角if(bord[i][j]=='Q'){return false;}}for(int i=row,j=colum;i>=0&&j<n;i--,j++){//判断右上角if(bord[i][j]=='Q'){return false;}}return true;}void Backtrack(char bord[][N],int n,int row){if(row>=n){print(bord,n);count++;printf("\n");return ;}else{for(int colum=0;colum<n;colum++){if(isselect(bord,row,colum,n)){bord[row][colum] = 'Q';Backtrack(bord,n,row+1);bord[row][colum] = '*';}}}
}int main()
{int n;printf("请输入皇后个数:\n");scanf("%d",&n);char bord[N][N]={'*'};printf("皇后摆放形式如下:\n");Backtrack(bord,n,0);printf("%d后问题共有%d种摆放方案 ",n,count);return 0;
}

【运行效果】

部分资料参考:代码随想录; 

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

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

相关文章

Git—文件添加查看删除修改

目录 1.添加文件—场景一 2.查看.git文件 3.添加文件—场景三 4.修改文件 5.版本回退 6.撤销修改 7.删除文件 1.添加文件—场景一 在包含.git的目录下新建⼀个ReadMe文件&#xff0c;我们可以使用 git add 命令可以将文件添加到暂存 区&#xff1a; ●添加一个或多个文…

Matlab数学建模算法之小波神经网络详解

&#x1f517; 运行环境&#xff1a;Matlab &#x1f6a9; 撰写作者&#xff1a;左手の明天 &#x1f947; 精选专栏&#xff1a;《python》 &#x1f525; 推荐专栏&#xff1a;《算法研究》 &#x1f510;#### 防伪水印——左手の明天 ####&#x1f510; &#x1f497; 大家…

存储成本降71%,怪兽充电历史库迁移OceanBase

怪兽充电作为共享充电宝第一股&#xff0c;业务增长迅速&#xff0c;以至于业务架构不停地增加组件。在验证 OceanBase 可以简化架构并带来更大的业务价值后&#xff0c;首次尝试在历史库中使用 OceanBase 替代 MySQL&#xff0c;存储成本降低 71%。本文为怪兽充电运维架构部王…

Docker 入门

Docker 入门 基础 不同操作系统下其安装包、运行环境是都不相同的&#xff01;如果是手动安装&#xff0c;必须手动解决安装包不同、环境不同的、配置不同的问题 而使用Docker&#xff0c;这些完全不用考虑。就是因为Docker会自动搜索并下载MySQL。注意&#xff1a;这里下载…

【C++】输入输出流 ⑥ ( cout 标准输出流对象 | cout 常用 api 简介 | cout.put(char c) 函数 )

文章目录 一、cout 标准输出流对象1、cout 标准输出流对象简介2、cout 常用 api 简介 二、cout.put(char c) 函数1、cout.put(char c) 函数 简介2、代码示例 - cout.put(char c) 函数 一、cout 标准输出流对象 1、cout 标准输出流对象简介 cout 是 标准输出流 对象 , 是 ostrea…

端口被占用 --- 解决方案

问题描述 加速服务启动失败&#xff0c;443端口被magentproc(1576)占用。请关掉占用443端口的程序或者尝试使用系统代理模式。 问题解决 按下 win R 打开 输入cmd 输入命令 netstat -ano | findstr 443 找到 0.0.0.0:443 对应的端口 (1576) 按下 ctrl shift esc, 打开任务管…

综述 2023-IEEE-TCBB:生物序列聚类方法比较

Wei, Ze-Gang, et al. "Comparison of methods for biological sequence clustering." IEEE/ACM Transactions on Computational Biology and Bioinformatics (2023). https://ieeexplore.ieee.org/document/10066180 被引次数&#xff1a;1&#xff1b;研究背景&am…

力扣题:数字与字符串间转换-12.13

力扣题-12.13 [力扣刷题攻略] Re&#xff1a;从零开始的力扣刷题生活 力扣题1&#xff1a;442. 数组中重复的数据 解题思想&#xff1a;直接相除即可 class Solution(object):def optimalDivision(self, nums):""":type nums: List[int]:rtype: str"&qu…

Transformer 简介

Transformer 是 Google 在 2017 年底发表的论文 Attention Is All You Need 中所提出的 seq2seq 模型。Transformer 模型的核心是 Self-Attention 机制&#xff0c;能够处理输入序列中的每个元素&#xff0c;并能计算其与序列中其他元素的交互关系的方法&#xff0c;从而能够更…

再见了Future,图解JDK21虚拟线程的结构化并发

Java为我们提供了许多启动线程和管理线程的方法。在本文中&#xff0c;我们将介绍一些在Java中进行并发编程的选项。我们将介绍结构化并发的概念&#xff0c;然后讨论Java 21中一组预览类——它使将任务拆分为子任务、收集结果并对其进行操作变得非常容易&#xff0c;而且不会不…

Unity中Shader黑白阀值后处理效果

文章目录 前言一、我们先来PS看一下黑白阀值的效果二、使用step(a,b)函数实现效果三、实现脚本控制黑白阀值1、在Shader属性面板定义控制阀值变量2、把step的a改为_Value3、在后处理脚本设置公共成员变量,并且设置范围为&#xff08;0&#xff0c;1&#xff09;4、在Graphics.B…

Cocos Creator:创建棋盘

Cocos Creator&#xff1a;创建棋盘 创建地图三部曲&#xff1a;1. 创建layout组件2. 创建预制体Prefab&#xff0c;做好精灵贴图&#xff1a;3. 创建脚本LayoutSprite.ts收尾工作&#xff1a; 创建地图三部曲&#xff1a; 1. 创建layout组件 使用layout进行布局&#xff0c;…

四十三、Redis基础

目录 一、认识NoSql 1、定义&#xff1a; 2、常见语法 3、与关系型数据库&#xff08;SQL&#xff09;的区别&#xff1a; 二、认识Redis 1、定义&#xff1a; 2、特征&#xff1a; 3、Key的结构&#xff1a; 三、安装Redis 四、Redis常见命令 1、数据结构介绍 2、…

关于DNS服务器地址总是127.0.0.1且无法解析域名地址

问题 笔者尝试nslookup解释域名时&#xff0c;出现服务器变成本地环回口地址&#xff0c;导致无法解析域名 C:\Users\Zsy>nslookup www.baidu.com 服务器: UnKnown Address: 127.0.0.1*** UnKnown 找不到 www.baidu.com: Server failed排查思路 尝试关闭虚拟网卡&#…

CSS的逻辑组合伪类

CSS 的逻辑组合伪类有 4 种&#xff0c;分别是&#xff1a;:not()、:is()、:where()和&#xff1a;has()。 否定伪类:not() :not 伪类选择器用来匹配不符合一组选择器的元素。由于它的作用是防止特定的元素被选中&#xff0c;它也被称为反选伪类&#xff08;negation pseudo-…

自动化测试框架 —— pytest框架入门篇

今天就给大家说一说pytest框架。 今天这篇文章呢&#xff0c;会从以下几个方面来介绍&#xff1a; 01、pytest框架介绍 pytest 是 python 的第三方单元测试框架&#xff0c;比自带 unittest 更简洁和高效&#xff0c;支持非常丰富的插件&#xff0c;同时兼容 unittest 框架。…

【C++】:AVL树

朋友们、伙计们&#xff0c;我们又见面了&#xff0c;本期来给大家解读一下有关多态的知识点&#xff0c;如果看完之后对你有一定的启发&#xff0c;那么请留下你的三连&#xff0c;祝大家心想事成&#xff01; C 语 言 专 栏&#xff1a;C语言&#xff1a;从入门到精通 数据结…

用python 网络自动化统计交换机有多少端口UP

用python统计交换机有多少端口UP 用python统计交换机有多少端口UP&#xff0c;可以间接的反馈有多少个用户在线。我们使用上次的脚本将可达的网络设备ip统计到reachable_ip.txt中&#xff0c;这次我们使用reachable_ip.txt来登陆设备来统计多少端口是UP的 云配置 拓扑 交换机…

【Cisco Packet Tracer】VLAN通信 多臂/单臂路由/三层交换机

在进行本文的实验之前&#xff0c;请确保掌握以下内容&#xff1a; 【Cisco Packet Tracer】交换机 学习/更新/泛洪/VLAN实验 【Cisco Packet Tracer】路由器实验 静态路由/RIP/OSPF/BGP 【Cisco Packet Tracer】路由器 NAT实验 本文介绍VLAN间的通信方法&#xff0c; 包括…

FreeRTOS的任务优先级、Tick以及状态讲解(尊敬的嵌入式工程师,不妨进来喝杯茶)

任务优先级和Tick 在FreeRTOS中&#xff0c;任务的优先级和Tick是两个关键的概念&#xff0c;它们直接影响任务的调度和执行。 任务优先级 每个任务都被分配一个优先级&#xff0c;用于决定任务在系统中的调度顺序。 优先级是一个无符号整数&#xff0c;通常从0开始&#xff0…