当前位置: 首页 > news >正文

深搜练习(N皇后)(10)

一.题目

51. N 皇后 - 力扣(LeetCode)

二.思路讲解

2.1 思路讲解

N皇后问题是回溯算法的经典应用。我们采用逐行放置的策略:每一行只能放一个皇后,因此行冲突自然避免。接下来只需要确保放置的皇后不与之前任何皇后在同一列或同一对角线即可。为此,我们需要维护三个布尔数组(哈希表)来记录被占用的列、主对角线和副对角线。

  • 列判断:用一个数组checkCol记录哪些列已被占用。

  • 主对角线:在棋盘上,同一主对角线上的格子满足行号 - 列号为常数。由于这个差值可能为负数,我们统一加上一个偏移量(例如n),映射到非负下标,用数组checkDig1记录。

  • 副对角线:同一副对角线上的格子满足行号 + 列号为常数,该值范围在[0, 2n-2],直接用数组checkDig2记录。

递归过程:从第 0 行开始,依次尝试每一列。如果当前位置的三个方向都未被占用,则放置皇后,并标记三个方向;然后递归处理下一行;递归返回后,撤销标记(回溯),继续尝试下一列。当成功放置完所有行时,将当前棋盘状态加入结果集。

剪枝:在尝试每一列时,若发现列或对角线已被占用,则直接跳过,不进入递归。这种提前判断避免了无效的放置,是回溯剪枝的典型应用。

三.代码演示

class Solution { public: bool checkCol[10],checkDig1[20],checkDig2[20];//x轴,主对角线,副对角线 vector<vector<string>>ret; vector<string>path; vector<vector<string>> solveNQueens(int n) { path.resize(n); for(int i = 0;i < n;i++) { path[i].append(n,'.');//初始化棋盘 } dfs(n,0); return ret; } void dfs(int n,int row) { if(row == n) { ret.push_back(path); return; } for(int col = 0;col < n;col++) { //剪枝判断x轴、主对角线、副对角线是否合法 if(checkCol[col] != true && checkDig1[row - col + n] != true && checkDig2[row + col] != true) { path[row][col] = 'Q'; checkCol[col] = checkDig1[row - col + n] = checkDig2[row + col] = true;//表示使用 dfs(n,row + 1); //回溯 path[row][col] = '.'; checkCol[col] = checkDig1[row - col + n] = checkDig2[row + col] = false;//表示空闲 } } } };

四.代码讲解

一、全局变量设计

为了实现回溯并记录棋盘状态,我们定义以下成员变量

  • checkCol[10]:布尔数组,记录每一列是否已被占用。由于 n ≤ 9,大小 10 足够。

  • checkDig1[20]:布尔数组,记录每条主对角线是否已被占用。主对角线上的格子满足row - col为常数,范围[-(n-1), n-1],加上偏移量n后映射到[1, 2n-1],大小 20 足够。

  • checkDig2[20]:布尔数组,记录每条副对角线是否已被占用。副对角线上的格子满足row + col为常数,范围[0, 2n-2],大小 20 足够。

  • ret:二维字符串数组,存储所有解,每个解是一个字符串向量(棋盘)。

  • path:一维字符串数组,表示当前正在构建的棋盘(每一行是一个字符串)。

二、主函数solveNQueens

主函数接收整数n,首先将path大小调整为n,并用'.'初始化每一行的所有列,形成一个n × n的棋盘。然后调用递归函数dfs(n, 0)从第 0 行开始放置皇后,最后返回结果集ret

三、递归函数dfs

递归函数dfs(int n, int row)的含义是:已经在前row行成功放置了皇后,接下来要在第row行放置皇后。执行流程如下:

1. 递归终止条件

row == n时,说明所有 n 行都已成功放置皇后,得到一个完整解,将当前棋盘path的副本加入ret,然后返回。

2. 遍历列并尝试放置

使用for循环遍历当前行的每一列col(0 到 n-1)。对于每一列,检查当前位置是否与已放置的皇后冲突:

  • 列冲突checkCol[col] == false

  • 主对角线冲突checkDig1[row - col + n] == false(加n防止负数下标)

  • 副对角线冲突checkDig2[row + col] == false

如果三个条件都满足(即均为false),则可以在(row, col)放置皇后:

  • 将棋盘path[row][col]设为'Q'

  • 将三个方向标记为已占用:checkCol[col] = truecheckDig1[row - col + n] = truecheckDig2[row + col] = true

  • 递归调用dfs(n, row + 1),处理下一行。

  • 递归返回后,执行回溯

    • path[row][col]恢复为'.'

    • 将三个方向的标记恢复为false,以便尝试其他列。

四、关键细节
  • 数组大小:n ≤ 9 时,row - col最小为-(n-1),加n后最小为 1;最大为(n-1) + n = 2n-1 ≤ 17row + col最大为2n-2 ≤ 16。因此checkDig1checkDig2大小 20 足够。

  • 下标偏移:主对角线索引通过row - col + n映射到非负范围,避免了负数下标。

http://www.jsqmd.com/news/760100/

相关文章:

  • 新政下的绿电直连项目经济性分析:模式创新与价值重构
  • 为内部AI助手工具配置安全的API访问控制与审计日志
  • 避坑指南:解决ORB-SLAM2+octomap建图时点云倾斜和rviz警告问题
  • 企业如何利用Taotoken构建稳定低延迟的AI视频处理管线
  • AUTOSAR Fee 模块深度解析:FeeBlock 与 Sector 数据结构勘误、工程实现与掉电保护实战
  • TrguiNG终极指南:5分钟打造高效Transmission远程管理界面
  • 雀魂牌谱屋:免费开源的麻将牌谱数据分析终极指南
  • 【Excel提效 No.045】一句话搞定数据分组小计自动生成
  • CNSH-QFLOW-WUXING-CORE v1.1:基于易经哲学的量子启发语义流场计算框架
  • 从0到1掌握DeerFlow:字节跳动开源AI Agent框架,轻松构建企业级智能体平台!
  • ChatGPT横空出世!大模型浪潮席卷全球,国产模型崛起,你该用哪个?深度解析大模型的一切!
  • QuantVLA:无需训练的视觉-语言-动作模型量化技术
  • Nemotron-Flash:低延迟LLM推理的混合小型语言模型架构
  • STM32基础驱动系列-DS18B20
  • 高效便捷!macOS 这 5 款命令行工具免费易装,让操作更高效
  • Claude Code 终于能在手机上跑了:10k Star 开源 UI,浏览器一进就有
  • Cortex-M55 CTI架构与调试技术详解
  • 英伟达:离线策略蒸馏Lightning OPD
  • 从“看图识字“到“全能感知“!多模态大模型5年爆变史,Qwen系成“基础设施“!
  • Nemotron-Flash:低延迟LLM推理的混合架构设计
  • 避坑指南:在Ubuntu 20.04上从零搭建OpenPCDet+PointPillars_ROS环境(含CUDA 11.7、spconv2.x配置)
  • Tool Calling 的实现细节——Agent 如何决定调用哪个工具
  • YOLO训练入门(下)学习笔记(第四集)
  • 【AI模型】模型量化技术详解
  • 大模型代码生成与代理任务评估框架及优化实践
  • 2026年5月专业靠谱的全屋定制TOP5:基于全案交付与口碑验证的权威榜单 - 商业科技观察
  • 告别手动测试:深入解读Vector CANoe LIN一致性测试模块(ISO17987/J2602标准覆盖哪些内容?)
  • 2026树枝粉碎机品牌评分出炉!博尚9.8分领跑,全能配置+高性价比,市政/物业首选品牌 - 会飞的懒猪
  • 大模型输入的“灵魂”步骤:Embedding如何让0、1、2变得有“意义”?
  • 2026年5月全屋定制品牌权威盘点:精工智造如何定义家的品质 - 商业科技观察