N皇后问题

1题目

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

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

 

2链接

题目链接:51. N 皇后 - 力扣(LeetCode)

视频链接:这就是传说中的N皇后? 回溯算法安排!| LeetCode:51.N皇后_哔哩哔哩_bilibili

3解题思路

这个题属实有点烦

首先来看一下皇后们的约束条件:

  1. 不能同行
  2. 不能同列
  3. 不能同斜线

搜索皇后的位置,可以抽象为一棵树。

下面我用一个 3 * 3 的棋盘,将搜索过程抽象为一棵树,如图:

(*狗屎,ctrl+z给我全部撤销完了,他奶奶的)

从图中,可以看出,二维矩阵中矩阵的高就是这棵树的高度,矩阵的宽就是树形结构中每一个节点的宽度。

那么我们用皇后们的约束条件,来回溯搜索这棵树,只要搜索到了树的叶子节点,说明就找到了皇后们的合理位置了

回溯三部曲:

1、确定函数参数及返回值

定义全局变量二维数组result来记录最终结果。

参数n是棋盘的大小,然后用row来记录当前遍历到棋盘的第几层了。

vector<vector<string>> result;
void backtracking(int n, int row, vector<string>& chessboard) {

2、确定递归终止条件

由上图可以看出,当递归到棋盘最底层(也就是叶子节点)的时候,就可以收集结果并返回了。

if (row == n) {
    result.push_back(chessboard);
    return;
}

3、确定单层搜索逻辑

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

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

for (int col = 0; col < n; col++) {
    if (isValid(row, col, chessboard, n)) { // 验证合法就可以放
        chessboard[row][col] = 'Q'; // 放置皇后
        backtracking(n, row + 1, chessboard);
        chessboard[row][col] = '.'; // 回溯,撤销皇后
    }
}

前面的回溯搞完了,剩下的就是判定合法性了

去重标准:

  1. 不能同行
  2. 不能同列
  3. 不能同斜线 (45度和135度角)

这里要注意了,实际上不用显式的去重行。因为回溯算法的特性,每一次递归都会在下一行中放置皇后,因此不可能在同一行中出现两个皇后。也就是说,在isValid的调用过程中,只有一行中的一个位置会被检查,因此不需要显式地检查该行是否已经放置了皇后。

不能同列:递归到第row行,且for循环遍历到第col列时-->检查第0-row行第col列是否已经出现了Q,如果出现则已不能再放置,设为不合法。

    for (int i = 0; i < row; i++) { // 这是一个剪枝
        if (chessboard[i][col] == 'Q') {
            return false;
        }
    }

不能同45°斜线:递归到第row行col列时,以此格左上角的一格为起点,一直往左上角去搜索(行--,列--),看是否出现了皇后

    for (int i = row - 1, j = col - 1; i >=0 && j >= 0; i--, j--) {
        if (chessboard[i][j] == 'Q') {
            return false;
        }
    }

不能同135°斜线:递归到第row行col列时,以此格右上角的一格为起点,一直往右上角去搜索(行--,列++),看是否出现了皇后

    for(int i = row - 1, j = col + 1; i >= 0 && j < n; i--, j++) {
        if (chessboard[i][j] == 'Q') {
            return false;
        }
    }

应该没得问题了,理一下整体思路:

row和col分别控制递归深度和广度-->递归到一个格子就检查合法性-->合法则在这个格子上放下皇后-->回溯-->递归到叶子节点收集结果。

4代码

class Solution {
private:
vector<vector<string>> result;
// n 为输入的棋盘大小
// row 是当前递归到棋盘的第几行了
void backtracking(int n, int row, vector<string>& chessboard) {
    if (row == n) {
        result.push_back(chessboard);
        return;
    }
    for (int col = 0; col < n; col++) {
        if (isValid(row, col, chessboard, n)) { // 验证合法就可以放
            chessboard[row][col] = 'Q'; // 放置皇后
            backtracking(n, row + 1, chessboard);
            chessboard[row][col] = '.'; // 回溯,撤销皇后
        }
    }
}
bool isValid(int row, int col, vector<string>& chessboard, int n) {
    // 检查列
    for (int i = 0; i < row; i++) { // 这是一个剪枝
        if (chessboard[i][col] == 'Q') {
            return false;
        }
    }
    // 检查 45度角是否有皇后
    for (int i = row - 1, j = col - 1; i >=0 && j >= 0; i--, j--) {
        if (chessboard[i][j] == 'Q') {
            return false;
        }
    }
    // 检查 135度角是否有皇后
    for(int i = row - 1, j = col + 1; i >= 0 && j < n; i--, j++) {
        if (chessboard[i][j] == 'Q') {
            return false;
        }
    }
    return true;
}
public:
    vector<vector<string>> solveNQueens(int n) {
        result.clear();
        std::vector<std::string> chessboard(n, std::string(n, '.'));
        backtracking(n, 0, chessboard);
        return result;
    }
};

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

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

相关文章

电商--抢购总结

文章目录 业务流程业务难点技术难点技术方案技术方向具体落地客户端流控网关流控容器流控后端接口流控数据库流控 流控总结优化读取加速异步化流程处理系统扩容 压测监控 总结参考文献 业务流程 客户端抢购流程中会涉及到商品数据的读取用于商品展示&#xff0c;运营活动数据的…

Docker 概述与命令操作

一、Docker 概述 1、Docker的概念 • Docker是一个开源的应用容器引擎&#xff0c;基于go语言开发并遵循了apache2.0协议开源 • Docker是在Linux容器里运行应用的开源工具&#xff0c;是一种轻量级的“虚拟机” • Docker 的容器技术可以在一台主机上轻松为任何应用创建一…

【4】Midjourney常用技巧

【常用技巧】 本篇主要讲述MJ的常用技巧&#xff0c;围绕着一些常用指令的使用方法展开。 【版本切换】 在使用MJ时&#xff0c;最常用的技巧之一是版本切换。你可以在输入提示后添加"--v"加上相应的数字来实现版本切换。通常我默认使用MJ 4&#xff0c;偶尔会使用…

信创办公–基于WPS的EXCEL最佳实践系列 (设置多级列表)

信创办公–基于WPS的EXCEL最佳实践系列 &#xff08;设置多级列表&#xff09; 目录 应用背景操作步骤1、删除重复项2、部门绑定3、填入相关信息 应用背景 当我们在使用电子表格时&#xff0c;很多类型重复输入很麻烦&#xff0c;看起来也很复杂&#xff0c;我们就可以设置多级…

PCB材料选择与性能比较

PCB板被广泛应用于电子行业&#xff0c;作为电子设备的重要组成部分之一&#xff0c;负责连接各种电子元件。PCB板的性能直接影响着电子设备的质量和稳定性。而PCB板的材料选择则是影响PCB板性能的关键因素之一。本文将对常见PCB材料进行比较分析&#xff0c;以便于选择适合的材…

SQL-基础

SQL-小基础 1 SQL简介 英文&#xff1a;Structured Query Language&#xff0c;简称 SQL结构化查询语言&#xff0c;一门操作关系型数据库的编程语言定义操作所有关系型数据库的统一标准对于同一个需求&#xff0c;每一种数据库操作的方式可能会存在一些不一样的地方&#xff…

第9章:SpringMVC的拦截器

一、拦截器 1.拦截器的配置 SpringMVC中的拦截器用于拦截控制器方法的执行SpringMVC中的拦截器需要实现HandlerInterceptorSpringMVC的拦截器必须在SpringMVC的配置文件进行配置 ①创建拦截器&#xff0c;继承接口HandlerInterceptor. Component public class FirstIntercep…

Log4j2漏洞复现补丁绕过

漏洞复现 这里我一共使用了两个jdk版本 8u202的情况比较特殊&#xff0c;其实我今天凌晨在家里用的也是8u202的版本&#xff0c;失败了。今天来公司也是用的8u202版本的jdk&#xff0c;成功了。我仔细研究了两者的不同&#xff0c;我发现唯一不同的就是我公司这个idea启的proie…

Spring Cloud Feign实战

概述 Feign是一种声明式、模板化的HTTP Client&#xff0c;目标是使编写Java HTTP Client变得更简单。Feign通过使用Jersey和CXF等工具实现一个HTTP Client&#xff0c;用于构建REST或SOAP的服务。Feign还支持用户基于常用的HTTP工具包&#xff08;OkHTTP、HTTPComponents&…

全志V3S嵌入式驱动开发(开发环境再升级)

【 声明&#xff1a;版权所有&#xff0c;欢迎转载&#xff0c;请勿用于商业用途。 联系信箱&#xff1a;feixiaoxing 163.com】 前面我们陆陆续续开发了差不多有10个驱动&#xff0c;涉及到网口、串口、音频和视频等几个方面。但是整个开发的效率还是比较低的。每次开发调试的…

Java中查看堆里的信息

文章目录 前言1 建议无脑的做一件事2 jmp命令3 导入 hprof 文件到Visual VM 中4 查看对象属性值 前言 日常工作中&#xff0c;我们可能会遇到这样的场景&#xff1a; java项目发生了OOM&#xff1b;想知道在某种场景下&#xff0c;堆里的信息&#xff0c;从而确认一些代码功能…

JavaCV音视频开发宝典:使用JavaCV读取海康平台或海康网络摄像头sdk回调视频TS码流并解析预览图像

《JavaCV音视频开发宝典》专栏目录导航 《JavaCV音视频开发宝典》专栏介绍和目录 ​ 前言 两年前博主写了如何利用JavaCV解析各种h264裸流,《JavaCV音视频开发宝典:使用javacv读取GB28181、海康大华平台和网络摄像头sdk回调视频码流并解析预览图像》,但是随着时间变化,各…

第五章 结构化设计

结构化设计的概念 1. 设计的定义 一种软件开发活动&#xff0c;定义实现需求规约所需的软件结构。 结构化设计分为&#xff1a; (1)总体设计&#xff1a;确定系统的整体模块结构&#xff0c;即系统实现所需要的软件模块以及这些模块之间的调用关系。 (2)详细设计&#xff1a;…

【C++】类型转换

目录 一、C语言中的类型转换 二、C中的类型转换 1.static_cast 2.reinterpret_cast 3.const_cast 4.dynamic_cast 三、RTTI 1.typeid运算符 2. decltype 一、C语言中的类型转换 在 C 语言中&#xff0c;如果 赋值运算符左右两侧类型不同&#xff0c;或者形参与实参类…

什么是域控服务器?域控服务器功能?部署域控需要考虑因素?域控组策略功能?

一、什么是域控制服务器&#xff1f; 域控制器&#xff08;Domain Controller&#xff09;是在Windows Server操作系统上运行的一个服务角色&#xff0c;它用于管理和控制一个或多个计算机的安全策略、用户身份验证和授权等任务。域控制器通常是用于企业网络中的主要身份验证和…

macOS Sonoma 14beta With OpenCore 0.9.3 and winPE双引导分区黑苹果原版镜像

镜像特点&#xff08;原文地址&#xff1a;http://www.imacosx.cn/113888.html&#xff09; 完全由黑果魏叔官方制作&#xff0c;针对各种机型进行默认配置&#xff0c;让黑苹果安装不再困难。系统镜像设置为双引导分区&#xff0c;全面去除clover引导分区&#xff08;如有需要…

华为OD机试真题 JavaScript 实现【IPv4地址转换成整数】【2023 B卷 100分】

一、题目描述 存在一种虚拟 IPv4 地址&#xff0c;由4小节组成&#xff0c;每节的范围为0~255&#xff0c;以#号间隔&#xff0c; 虚拟 IPv4 地址可以转换为一个32位的整数&#xff0c;例如&#xff1a; 128#0#255#255&#xff0c;转换为32位整数的结果为2147549183&#xff0…

vue制作自己的组件库(仿ElementUI)

1.首先自己创建个新的vue项目&#xff0c;之后更改下目录形式&#xff0c;将src文件更改为examples&#xff0c;这里是专门放组件展示的md文件&#xff0c;packages文件里是放自己写的组件代码 2.然后是开始配置vue.config.js文件 &#xff0c;其中md-loader是读取md文件的相关…

【C/C++】带你快速掌握 使用—增强for(范围for循环)

创作不易&#xff0c;本篇文章如果帮助到了你&#xff0c;还请点赞 关注支持一下♡>&#x16966;<)!! 主页专栏有更多知识&#xff0c;如有疑问欢迎大家指正讨论&#xff0c;共同进步&#xff01; &#x1f525;c系列专栏&#xff1a;C/C零基础到精通 &#x1f525; 给大…

MySQL 存储过程

1 什么是存储过程 MySQL 5.0 版本开始支持存储过程存储过程&#xff08;Stored Procedure&#xff09;是一种在数据库中存储复杂程序&#xff0c;以便外部程序调用的一种数据 库对象。存储过程是为了完成特定功能的SQL语句集&#xff0c;经编译创建并保存在数据库中&#xff0…
最新文章