回溯法c++学习 解决八皇后问题
使用回溯法解决八皇后问题
八皇后问题是一个以国际象棋为背景的问题:如何能够在8×8
的国际象棋棋盘上放置八个皇后,使得任何一个皇后都无法直接吃掉其他的皇后?为了达到此目的,任两个皇后都不能处于同一条横行、纵行或斜线上。这个问题可以推广为更一般的n 皇后摆放问题,其中棋盘的大小变为n×n ,而皇后个数也变成n 。当且仅当n=1 或n≥4
时,问题有解
#include <iostream>
#include <vector>class Solution {
private:std::vector<std::vector<std::string>> results; // 存储所有有效的棋盘配置public:std::vector<std::vector<std::string>> solveNQueens(int n) {std::vector<std::string> board(n, std::string(n, '.')); // 初始化棋盘,全部填充为'.'backtrack(board, 0); // 从第0行开始回溯return results;}private:void backtrack(std::vector<std::string>& board, int row) {if (row == board.size()) { // 如果已经放置了n个皇后(到达最后一行之后),找到一个有效解results.push_back(board);return;}int n = board[row].size();for (int col = 0; col < n; col++) { // 尝试在当前行的每一列放置皇后if (isValid(board, row, col)) { // 检查在此位置放置皇后是否有效board[row][col] = 'Q'; // 放置皇后backtrack(board, row + 1); // 递归到下一行board[row][col] = '.'; // 回溯,撤销这个位置的皇后}}}bool isValid(const std::vector<std::string>& board, int row, int col) {int n = board.size();// 检查同一列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 < n; i--, j++) {if (board[i][j] == 'Q') return false;}return true; // 如果通过所有检查,则此位置有效}
};int main() {Solution solution;auto results = solution.solveNQueens(8); // 解决8皇后问题// 打印所有解for (int i = 0; i < results.size(); i++) {std::cout << "Solution " << i + 1 << ":\n";for (const auto& row : results[i]) {std::cout << row << "\n";}std::cout << "\n";}std::cout << "Total solutions: " << results.size() << std::endl;return 0;
}
这段代码的详细解释如下:
- 我们定义了一个
Solution
类来封装解决方案。 results
成员变量用于存储所有有效的棋盘配置。solveNQueens
函数是主入口点,它初始化棋盘并开始回溯过程。backtrack
函数实现了回溯算法:- 如果已经成功放置了n个皇后,我们就找到了一个有效解。
- 否则,我们尝试在当前行的每一列放置皇后。
- 如果某个位置有效,我们就放置皇后,然后递归到下一行。
- 在回溯时,我们撤销这个位置的皇后。
isValid
函数检查在特定位置放置皇后是否有效:- 检查同一列是否已有皇后。
- 检查左上对角线是否已有皇后。
- 检查右上对角线是否已有皇后。
- 在
main
函数中,我们创建Solution
对象,解决8皇后问题,并打印所有解。
这个算法的时间复杂度是O(N!),其中N是棋盘的大小(在这里是8)。这是因为在最坏的情况下,我们需要尝试所有可能的排列。空间复杂度是O(N),主要用于递归调用栈和存储棋盘状态。
这个解决方案使用了回溯法,它通过系统地尝试所有可能的配置来找到所有有效的解。每当发现当前路径不可行时,它就回溯并尝试下一个可能的选择。
但是八皇后问题的最有效的算法是位运算法
#include <iostream>
using namespace std;// 位运算解决八皇后问题
void solveNQueens(int n) {long upperlim = (1 << n) - 1; // 初始化,upperlim 表示 n 个皇后的所有列都已放置好long Ans = 0; // 记录解的个数// 递归函数,寻找可以放置皇后的位置void test(long row, long ld, long rd) {if (row != upperlim) {// pos 表示当前行可以放置皇后的位置long pos = upperlim & (~(row | ld | rd));while (pos) {// 取出最右边的可以放皇后的位置long p = pos & (-pos);pos -= p; // 移除该位置并递归调用 test 过程// 更新限制条件long new_ld = (ld | p) << 1;long new_rd = (rd | p) >> 1;test(row | p, new_ld, new_rd);}} else {++Ans; // 找到一个解}}// 调用参数test(0, 0, 0);cout << "共有 " << Ans << " 种排列" << endl;
}int main() {int n = 8; // 八皇后问题solveNQueens(n);return 0;
}
这段代码使用了位运算来高效地解决八皇后问题。核心思想是用一个整数变量表示每一行中哪些位置已经被占用,然后通过位运算判断某个位置是否可以放置皇后。具体解释如下:
upperlim
初始化为2n−1,表示 n 个皇后的所有列都已放置好。test
函数是递归的,它寻找可以放置皇后的位置。参数row
、ld
和rd
分别表示在纵列和两个对角线方向的限制条件下,这一行的哪些地方不能放。- 位于该行上的冲突位置用
row
、ld
和rd
中的 1 来表示。将它们三个进行并操作,得到该行所有的禁位,取反后就得到所有可以放的位置(用pos
表示)。 p = pos & (-pos)
取出pos
最右边的那个 1,表示该行的某个可以放子的位置。将它从pos
中移除并递归调用test
过程。- 注意递归调用时三个参数的变化,每个参数都加上了一个禁位,但两个对角线方向的禁位对下一行的影响需要平移一位。
- 最后,如果递归到某个时候发现
row = upperlim
,说明 n 个皇后全放进去了,找到的解的个数加一。
相关文章:
回溯法c++学习 解决八皇后问题
使用回溯法解决八皇后问题 八皇后问题是一个以国际象棋为背景的问题:如何能够在88 的国际象棋棋盘上放置八个皇后,使得任何一个皇后都无法直接吃掉其他的皇后?为了达到此目的,任两个皇后都不能处于同一条横行、纵行或斜线上。这…...

5. Spring IoCDI ★ ✔
5. Spring IoC&DI 1. IoC & DI ⼊⻔1.1 Spring 是什么?★ (Spring 是包含了众多⼯具⽅法的 IoC 容器)1.1.1 什么是容器?1.1.2 什么是 IoC?★ (IoC: Inversion of Control (控制反转))总…...

数据库自动备份到gitee上,实现数据自动化备份
本人有个不太好的习惯,每次项目的数据库都是在线上创建,Navicat 连接线上数据库进行处理,最近有一个项目需要二次升级,发现老项目部署的服务器到期了,完蛋,数据库咩了!!!…...
探索 Spring Cloud Gateway:构建微服务架构的关键一环
1. 简介 在当今的分布式系统中,微服务架构已经成为了一种流行的架构模式。在微服务架构中,服务被拆分为小型、可独立部署的服务单元,这些服务单元能够通过网络互相通信,形成一个整体的应用系统。然而,随着微服务数量的…...
P1114 “非常男女”计划最优解
原题地址 P1114 “非常男女”计划 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn) 代码题解 AC代码(1) 因为用的是级的算法,所以最后一个 了,这里使用特判来得到的,给你们放一下代码: #include <bi…...

C++ | Leetcode C++题解之第187题重复的DNA序列
题目: 题解: class Solution {const int L 10;unordered_map<char, int> bin {{A, 0}, {C, 1}, {G, 2}, {T, 3}}; public:vector<string> findRepeatedDnaSequences(string s) {vector<string> ans;int n s.length();if (n < L…...
构建、标记和发布镜像
构建、标记和发布镜像 目录 构建镜像标记镜像发布镜像实践 设置构建镜像推送镜像 在本指南中,您将学习以下内容: 构建镜像:基于Dockerfile构建镜像的过程。标记镜像:为镜像命名的过程,这也决定了镜像的分发位置。发…...

[Go Web] Kratos 使用的简单总结
文章目录 1.Kratos 简介2.传输协议3.日志4.错误处理5.配置管理6.wire 1.Kratos 简介 Kratos并不绑定于特定的基础设施,不限定于某种注册中心,或数据库ORM等,所以您可以十分轻松地将任意库集成进项目里,与Kratos共同运作。 API -&…...

首个实时 AI 视频生成技术发布;科大讯飞发布星火大模型 4.0 丨 RTE 开发者日报
开发者朋友们大家好: 这里是 「RTE 开发者日报」 ,每天和大家一起看新闻、聊八卦。我们的社区编辑团队会整理分享 RTE(Real-Time Engagement) 领域内「有话题的新闻」、「有态度的观点」、「有意思的数据」、「有思考的文章」、「…...
什么是容器镜像
什么是容器镜像? 1. 容器镜像的两个重要原则 容器镜像是容器化应用程序的基础,它包含了运行应用程序所需的一切——代码、运行时、库和依赖项。理解容器镜像的两个重要原则非常重要: 不可变性:容器镜像一旦构建,就不…...

ElasticSearch-Windows系统ElasticSearch(ES)的下载及安装
前言 下载ElasticSearch 可以进入ElasticSearch官方下载地址,选择与电脑系统相对应的版本;博主已经上传资源,或者点此直接免费下载,本次演示版本为8.14.1。 注意: Elasticsearch 5 需要 Java 8 以上版本;…...

【应用开发二】GPIO操控(输出、输入、中断)
1 操控GPIO方式 控制目录:/sys/class/gpio /sys/class/gpio目录下文件如下图所示: 1.1 gpiochipX目录 功能:当前SoC所包含的所有GPIO控制器 i.mx6ull一共包含5个GPIO控制器,分别为GPIO1~5分别对应gpiochip0、gpiochip32、gpi…...
单点登录方法
一、父域cookie:两个有相同父域名的二级域名之间可以跨域传递cookie //注意该接口的地址也是baidu.com下属的二级域名:a.baidu.com //全部接口地址为:a.baidu.com/dev-api/system/ecdWeb/login。如果不是a.baidu.com那么根本带不过去 //其实可以理解为通过该方法将cookie传给…...
springboot集成JPA并配置hikariCP连接池问题解决
一、引入需要的依赖 springboot版本 <parent><groupId>org.springframework.boot</groupId><artifactId>spring-boot-parent</artifactId><version>2.3.2.RELEASE</version><relativePath/></parent> jpa依赖 <!--…...
vue2的双向绑定
vue是一个mvvm框架,即数据双向绑定,即当数据发生变化的时候,视图也就发生变化,当视图发生变化的时候,数据也会跟着同步变化。 Vue.js 2 中的双向绑定是通过 v-model 指令实现的。v-model 指令可以在表单输入元素上创建…...

Vue3 国际化i18n
国际化i18n方案 1. 什么是i18n2. i18n安装、配置及使用2.1 安装2.2 配置2.3 挂载到实例2.4 组件中使用2.5 语言切换 1. 什么是i18n i18n 是“国际化”的简称。在资讯领域,国际化(i18n)指让产品(出版物,软件,硬件等)无…...
算法金 | 使用随机森林获取特征重要性
大侠幸会幸会,我是日更万日 算法金;0 基础跨行转算法,国内外多个算法比赛 Top;放弃 BAT Offer,成功上岸 AI 研究院 Leader; <随机森林及其应用领域> 随机森林是一种强大的机器学习算法,其…...
网络安全的重要性
网络安全的重要性 网络安全是指保护网络系统免受未授权的访问、攻击、破坏或未经授权的数据泄露的能力。随着互联网的普及和数字化进程的加速,网络安全问题日益凸显,成为个人、企业和国家必须面对的重要挑战。 网络安全的威胁 网络安全威胁包括黑客攻…...
Leetcode40 无重复组合之和
题目描述: 给定一个候选人编号的集合 candidates 和一个目标数 target ,找出 candidates 中所有可以使数字和为 target 的组合。 candidates 中的每个数字在每个组合中只能使用 一次 。 注意:解集不能包含重复的组合。 思路分析 这个题是…...
详解MATLAB中处理日期和时间的函数
在MATLAB中处理日期和时间时,可以使用多种函数来进行计时和时间差计算。以下是对一些常用函数的详细解释: 1. tic 和 toc 用途:用来测量一段代码执行的时间。用法:tic; % 启动秒表 % 你的代码 elapsedTime toc; % 停止秒表&…...
脑机新手指南(八):OpenBCI_GUI:从环境搭建到数据可视化(下)
一、数据处理与分析实战 (一)实时滤波与参数调整 基础滤波操作 60Hz 工频滤波:勾选界面右侧 “60Hz” 复选框,可有效抑制电网干扰(适用于北美地区,欧洲用户可调整为 50Hz)。 平滑处理&…...
1688商品列表API与其他数据源的对接思路
将1688商品列表API与其他数据源对接时,需结合业务场景设计数据流转链路,重点关注数据格式兼容性、接口调用频率控制及数据一致性维护。以下是具体对接思路及关键技术点: 一、核心对接场景与目标 商品数据同步 场景:将1688商品信息…...

Netty从入门到进阶(二)
二、Netty入门 1. 概述 1.1 Netty是什么 Netty is an asynchronous event-driven network application framework for rapid development of maintainable high performance protocol servers & clients. Netty是一个异步的、基于事件驱动的网络应用框架,用于…...
django blank 与 null的区别
1.blank blank控制表单验证时是否允许字段为空 2.null null控制数据库层面是否为空 但是,要注意以下几点: Django的表单验证与null无关:null参数控制的是数据库层面字段是否可以为NULL,而blank参数控制的是Django表单验证时字…...
全面解析数据库:从基础概念到前沿应用
在数字化时代,数据已成为企业和社会发展的核心资产,而数据库作为存储、管理和处理数据的关键工具,在各个领域发挥着举足轻重的作用。从电商平台的商品信息管理,到社交网络的用户数据存储,再到金融行业的交易记录处理&a…...

算术操作符与类型转换:从基础到精通
目录 前言:从基础到实践——探索运算符与类型转换的奥秘 算术操作符超级详解 算术操作符:、-、*、/、% 赋值操作符:和复合赋值 单⽬操作符:、--、、- 前言:从基础到实践——探索运算符与类型转换的奥秘 在先前的文…...

sshd代码修改banner
sshd服务连接之后会收到字符串: SSH-2.0-OpenSSH_9.5 容易被hacker识别此服务为sshd服务。 是否可以通过修改此banner达到让人无法识别此服务的目的呢? 不能。因为这是写的SSH的协议中的。 也就是协议规定了banner必须这么写。 SSH- 开头,…...
【实施指南】Android客户端HTTPS双向认证实施指南
🔐 一、所需准备材料 证书文件(6类核心文件) 类型 格式 作用 Android端要求 CA根证书 .crt/.pem 验证服务器/客户端证书合法性 需预置到Android信任库 服务器证书 .crt 服务器身份证明 客户端需持有以验证服务器 客户端证书 .crt 客户端身份…...
电脑桌面太单调,用Python写一个桌面小宠物应用。
下面是一个使用Python创建的简单桌面小宠物应用。这个小宠物会在桌面上游荡,可以响应鼠标点击,并且有简单的动画效果。 import tkinter as tk import random import time from PIL import Image, ImageTk import os import sysclass DesktopPet:def __i…...

高保真组件库:开关
一:制作关状态 拖入一个矩形作为关闭的底色:44 x 22,填充灰色CCCCCC,圆角23,边框宽度0,文本为”关“,右对齐,边距2,2,6,2,文本颜色白色FFFFFF。 拖拽一个椭圆,尺寸18 x 18,边框为0。3. 全选转为动态面板状态1命名为”关“。 二:制作开状态 复制关状态并命名为”开…...