回溯法求解N皇后问题

目录

前言

一、回溯法是什么?

二、N皇后问题描述

分析解题思路

三、算法设计

1、递归法

2、非递归法

总结


前言

本文将从递归形式和非递归形式两种方法来介绍求解N皇后问题的回溯法,后续也会更新更多有关算法分析这方面的问题欢迎大家关注~🤩


一、回溯法是什么?

  1. 定义: 回溯法(Backtracking)是一种通过试探性搜索 来解决问题的算法思想,主要用于解决组合问题、决策问题和枚举问题
  2. 核心思想: **"尝试-回退"------**通过逐步构建可能的解,并在发现当前路径无法得到有效解时回退(回溯),尝试其他路径。

通俗的来讲其实回溯法就是一种更高效的穷举方法,而高效就体现在下面三种核心特点中:

  • 系统性搜索:按特定顺序(如深度优先)枚举所有可能的解。
  • 剪枝优化:在搜索过程中提前终止无效分支(如不满足约束条件时)。
  • 递归实现:通常用递归实现试探和回退步骤。

二、N皇后问题描述

N 皇后问题是指在 n * n 的棋盘上要摆 n 个皇后

要求:任何两个皇后++不同行,不同列也不在同一条斜线上++,求给一个整数 n ,返回 n 皇后的摆法数。

例如当输入4时,对应的返回值为2,对应的两种四皇后摆位如下图所示:

分析解题思路

我们可以先固定放入一个皇后,然后再根据条件放入另一个皇后,如果我们发现放到后面已经没有位置满足放皇后的条件了就说明我们前面的摆放肯定是有误,因此我们就要返回错误的一步重新摆放皇后,也就是回溯法的基本思想。

这里要求++不同行,不同列也不在同一条斜线上,++ 那我们就可以固定每个皇后的行分别为1~n ,然后我们再挑选不同的列放入皇后 并且++同时满足不在同一条斜线上++

那其实这里提到的不同列不同斜线就是我们的剪枝条件,我们在搜索的过程中将不满足条件的枝条减去,大大提升了搜索效率;下面是剪枝条件函数的定义:

在使用回溯法的时候,我们通常要定义全局变量,这样方便我们使用递归调用,不需要频繁的传参,这里我们使用x[ i ](i=1、2、3····n)来表示第i行的皇后放在第x[ i ]列,也就是用下标表示行号,值表示列号

cs 复制代码
bool Place(int t) {
    for (int i = 1; i < t; i++) {
        if ((abs(x[t] - x[i]) == abs(t - i)) || (x[t] == x[i]) )
            return false;
    }
    return true;
}

如图所示,如果两个皇后在同一条直线上,则她们的横纵坐标之差的绝对值应该相同。如果两个条件有一个不满足我们就返回false,说明不需要再向下查找了,需要修改当前皇后的位置。

三、算法设计

上面我们了解了怎么剪掉不满足条件的分支,那么我们怎么判断我们找到了一个可行解呢?

还是以四个皇后为例:

如图所示,我们易知假如把1皇后放在第一列,则2皇后不能放在1、2列,可以放在第三列,但此时再往后放3皇后的时候我们发现不管放在哪里都是错误的,则此时我们应该回到2皇后处,再放到第四列尝试,后面的以此类推(大家可以自己在纸上画一画);那么最后我们能够找到一个可行解就是找到了最后的叶节点,此时每个皇后都有位置

1、递归法

cs 复制代码
void Backtrack(int t) {
    if (t > n) {
        sum++;//说明此时已经找到一个可行解
    } else {
        for (int i = 1; i <= n; i++) {
            x[t] = i;
            if (Place(t))
                Backtrack(t + 1);//如果满足条件就继续往下搜索
          //假如不满足条件了,则返回,从这里开始进入循环,判断下一列是否满足条件


        }
    }

}

2、非递归法

传递的参数可以根据题目灵活调整,这里用k表示第k行

cs 复制代码
void Backtrack(int n) {
    x[1] = 0;
    k = 1;
    while (k > 0) {
        x[k] += 1;
        while (x[k] <= n && !Place(k))
            x[k]++;//一直往后加直到找到能够放置的位置
        if (x[k] <= n) {//没有超出可排的范围
            if (k == n) //找到了一个解
                sum++;
            else {
                k++;
                x[k] = 0;//每次都从第一列开始查找
            }
        } else
            k--;//如果都排到外面去了说明该行没有可防止的位置,回溯
    }
}

总结

回溯法是一种通过系统性试探和剪枝优化 来高效穷举所有可能解的算法,其核心思想是"尝试-回退",在解决组合问题时能显著减少无效搜索。以N皇后问题为例,算法通过递归或迭代逐行放置皇后,并利用约束条件(列、斜线冲突)剪枝,避免不必要的路径探索,从而在O(n!)的理论复杂度下实现实际高效求解。 回溯法不仅适用于N皇后这类经典问题,还可推广至数独、图着色等场景,体现了"智能穷举"的算法设计思想,其平衡了代码简洁性(递归)与执行效率(迭代),是解决NP难问题的重要工具。

相关推荐
de之梦-御风几秒前
【Winform】实现“下拉自动补全”通常指的是 ComboBox / TextBox 在输入时自动提示或补全匹配项
c#
过河卒_zh156676611 分钟前
情感型AI被“立规矩”,AI陪伴时代进入下半场
人工智能·算法·aigc·生成式人工智能·算法备案
m5655bj16 分钟前
如何通过 C# 快速生成二维码 QR Code
c#·visual studio
wefg120 分钟前
【算法】动态规划
算法·动态规划
机器学习之心30 分钟前
198种组合算法+优化TCN-Transformer+SHAP分析+新数据预测+多输出!深度学习可解释分析,强烈安利,粉丝必备!
深度学习·算法·transformer·shap分析·新数据预测
狐5731 分钟前
2026-01-12-LeetCode刷题笔记-1266-访问所有点的最小时间.md
笔记·算法·leetcode
Gorgous—l31 分钟前
数据结构算法学习:LeetCode热题100-栈篇(有效的括号、最小栈、字符串解码、每日温度、柱状图中最大的矩形)
数据结构·学习·算法
小郭团队32 分钟前
教育公平的探索
大数据·人工智能·嵌入式硬件·算法·硬件架构
瑞雨溪37 分钟前
力扣题解:740.删除并获得点数
算法·leetcode·职场和发展
LeeeX!39 分钟前
基于YOLO11实现明厨亮灶系统实时检测【多场景数据+模型训练、推理、导出】
深度学习·算法·目标检测·数据集·明厨亮灶