【回溯法经典】N皇后问题详解与C语言代码实现

前言

N皇后问题作为回溯法的经典题目,在算法界有着不可动摇的地位。如何优雅地通过回溯法枚举并筛选所有解?这篇博文不仅展示了代码,还有原理动画,助你彻底掌握~

一、问题描述

在n×n的棋盘上放n个皇后,使得任何两个皇后不处于同一行、同一列或同一对角线上(如图所示)。

二、算法建模

  • 解向量:x[i]表示第i行皇后摆放在哪一列(每行恰好一个皇后)
  • 显约束:每个皇后必须在列1~n
  • 隐约束:
    1. 不同行不同列
    2. 不同对角线: abs(i−j)!=abs(x[i]−x[j])

三、核心代码实现

#include <stdio.h>
#include <math.h>

#define N 20  /* 最大皇后数 */

int n, sum;
int x[N+1]; /* x[i] 记录第i行皇后放在第几列 */

int Place(int k) {
    int j;
    for (j = 1; j < k; j++) {
        if (abs(k - j) == abs(x[j] - x[k]) || x[j] == x[k])
            return 0;
    }
    return 1;
}

void Backtrack(int t) {
    int i;
    if (t > n) {
        sum++;
        for (i = 1; i <= n; i++)
            printf("%d ", x[i]);
        printf("\n");
    } else {
        for (i = 1; i <= n; i++) {
            x[t] = i;
            if (Place(t))
                Backtrack(t + 1);
        }
    }
}

int main(void) {
    printf("请输入皇后数n:");
    scanf("%d", &n);
    sum = 0;
    Backtrack(1);
    printf("共有%d种解法\n", sum);
    return 0;
}
解空间搜索树(4皇后问题):

由于对称性,省略放置(1,3),(1,4)。

棋盘解法(3皇后问题):

四、运行演示

以8皇后为例运行:

请输入皇后数n:8
1 5 8 6 3 7 2 4
1 6 8 3 7 4 2 5
1 7 4 6 8 2 5 3
1 7 5 8 2 4 6 3
2 4 6 8 3 1 7 5
2 5 7 1 3 8 6 4
2 5 7 4 1 8 6 3
2 6 1 7 4 8 3 5
2 6 8 3 1 4 7 5
2 7 3 6 8 5 1 4
2 7 5 8 1 4 6 3
2 8 6 1 3 5 7 4
3 1 7 5 8 2 4 6
3 5 2 8 1 7 4 6
3 5 2 8 6 4 7 1
3 5 7 1 4 2 8 6
3 5 8 4 1 7 2 6
3 6 2 5 8 1 7 4
3 6 2 7 1 4 8 5
3 6 2 7 5 1 8 4
3 6 4 1 8 5 7 2
3 6 4 2 8 5 7 1
3 6 8 1 4 7 5 2
3 6 8 1 5 7 2 4
3 6 8 2 4 1 7 5
3 7 2 8 5 1 4 6
3 7 2 8 6 4 1 5
3 8 4 7 1 6 2 5
4 1 5 8 2 7 3 6
4 1 5 8 6 3 7 2
4 2 5 8 6 1 3 7
4 2 7 3 6 8 1 5
4 2 7 3 6 8 5 1
4 2 7 5 1 8 6 3
4 2 8 5 7 1 3 6
4 2 8 6 1 3 5 7
4 6 1 5 2 8 3 7
4 6 8 2 7 1 3 5
4 6 8 3 1 7 5 2
4 7 1 8 5 2 6 3
4 7 3 8 2 5 1 6
4 7 5 2 6 1 3 8
4 7 5 3 1 6 8 2
4 8 1 3 6 2 7 5
4 8 1 5 7 2 6 3
4 8 5 3 1 7 2 6
5 1 4 6 8 2 7 3
5 1 8 4 2 7 3 6
5 1 8 6 3 7 2 4
5 2 4 6 8 3 1 7
5 2 4 7 3 8 6 1
5 2 6 1 7 4 8 3
5 2 8 1 4 7 3 6
5 3 1 6 8 2 4 7
5 3 1 7 2 8 6 4
5 3 8 4 7 1 6 2
5 7 1 3 8 6 4 2
5 7 1 4 2 8 6 3
5 7 2 4 8 1 3 6
5 7 2 6 3 1 4 8
5 7 2 6 3 1 8 4
5 7 4 1 3 8 6 2
5 8 4 1 3 6 2 7
5 8 4 1 7 2 6 3
6 1 5 2 8 3 7 4
6 2 7 1 3 5 8 4
6 2 7 1 4 8 5 3
6 3 1 7 5 8 2 4
6 3 1 8 4 2 7 5
6 3 1 8 5 2 4 7
6 3 5 7 1 4 2 8
6 3 5 8 1 4 2 7
6 3 7 2 4 8 1 5
6 3 7 2 8 5 1 4
6 3 7 4 1 8 2 5
6 4 1 5 8 2 7 3
6 4 2 8 5 7 1 3
6 4 7 1 3 5 2 8
6 4 7 1 8 2 5 3
6 8 2 4 1 7 5 3
7 1 3 8 6 4 2 5
7 2 4 1 8 5 3 6
7 2 6 3 1 4 8 5
7 3 1 6 8 5 2 4
7 3 8 2 5 1 6 4
7 4 2 5 8 1 3 6
7 4 2 8 6 1 3 5
7 5 3 1 6 8 2 4
8 2 4 1 7 5 3 6
8 2 5 3 1 7 4 6
8 3 1 6 2 5 7 4
8 4 1 3 6 2 7 5
共有92种解法

五、时间复杂度分析

每一行要放一个皇后,每个皇后有最多n个可选列,仅当不冲突时才递归下一层。

  • 完全枚举:有n!种可能,因为每行1个,每列只放1个皇后。
  • 剪枝优化:每次通过对角冲突/列冲突判断,显著剪去了大量无效分支,但最坏依然要枚举指数级解。
  • 复杂度:最坏情况为O(n!),实际要远低于_n{}^{n},高效实现(比如位运算)可提升性能,但指数级别不可避免。

六、总结与扩展

  • 本题核心:回溯剪枝。
  • 启发式优化:可以用位运算、对称性减少重复。
  • 面试、算法竞赛常客,熟练掌握必备!
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

TJUTCM-烛龙

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值