首页
▼ 算法合集
▼ 加密算法
▼ 凯撒密码
凯撒密码
▼ Hill密码算法
Hill密码算法
▼ 多项式哈希算法
多项式哈希算法
▼ Rail Fence Cipher
Rail Fence Cipher
▼ Graph算法
▼ 关节点
关节点
▼ Bellman-Ford算法
Bellman-Ford算法
▼ 广度优先搜索
广度优先搜索
▼ GraphBridges
桥接模式
▼ 深度优先搜索
深度优先搜索
▼ 检测循环
检测循环
▼ Dijkstra算法
Dijkstra算法
▼ Eulerian Path
欧拉路径
▼ Floyd-Warshall算法
Floyd-Warshall算法
▼ HamiltonianCycle
Hamiltonian Cycle
▼ Kruskal算法
Kruskal算法
▼ Prim算法
Prim算法
▼ 强连通分量
强连通分量
▼ 拓扑排序
拓扑排序
▼ Travelling Salesman Problem
Travelling Salesman
▼ 图像处理算法
▼ Seam Carving算法
内容感知缩放算法
▼ 链表
▼ 反向遍历
反向遍历
▼ GraphTraversal
GraphTraversal
▼ 数学算法
▼ 二进制浮点数
BinaryFloatingPoint
▼ 位操作
位操作算法
▼ 复数
复数
▼ 欧几里得算法
Euclidean Algorithm
▼ Euclidean Distance
欧几里得距离
▼ 阶乘算法
阶乘算法
▼ 快速幂算法
快速幂算法
▼ Fibonacci数列
斐波那契数列
▼ 傅里叶变换
Fourier变换
▼ Horner法
霍纳法则
▼ 整数划分
整数划分
▼ 判断是否为2的幂
判断是否为2的幂
▼ 最小公倍数
最小公倍数
▼ Liu Hui
Liu Hui
▼ 矩阵
Matrix
▼ Pascal三角形
Pascal三角形
▼ Primality Test
素数测试
▼ 质因数
质因数
▼ 弧度计算
弧度计算
▼ 埃拉托色尼筛法
埃拉托色尼筛法
▼ SquareRoot
SquareRoot
▼ MachineLearning
▼ K均值算法
K均值算法
▼ K近邻算法
K近邻算法
▼ 搜索算法
▼ 二分查找算法
二分查找
▼ 插值搜索算法
插值搜索算法
▼ 跳跃搜索算法
跳跃搜索算法
▼ 线性搜索
线性搜索算法
▼ 集合
▼ 笛卡尔积
笛卡尔积
▼ 组合总和
组合总和
▼ 组合算法
组合算法
▼ Fisher-Yates洗牌算法
Fisher-Yates洗牌算法
▼ 背包问题
背包问题
▼ 最长公共子序列
最长公共子序列
▼ 最长递增子序列
最长递增子序列
▼ 最大子数组
最大子数组
▼ 排列组合
排列组合
▼ 幂集
幂集算法
▼ 最短公共超序列
最短公共超序列
▼ Sorting Algorithms
▼ 冒泡排序
冒泡排序
▼ 桶排序算法
桶排序算法
▼ 计数排序算法
计数排序
▼ 堆排序算法
堆排序
▼ 插入排序
插入排序
▼ 归并排序
归并排序
▼ 快速排序算法
快速排序算法
▼ 基数排序
基数排序
▼ 选择排序算法
选择排序算法
▼ 希尔排序
希尔排序
▼ 统计学
▼ 加权随机
加权随机算法
▼ 字符串算法
▼ Hamming距离
Hamming距离
▼ KnuthMorrisPratt算法
Knuth-Morris-Pratt算法
▼ LevenshteinDistance
Levenshtein距离
▼ 最长公共子串
最长公共子串
▼ 回文检测算法
回文检测算法
▼ Rabin-Karp算法
Rabin-Karp算法
▼ 正则表达式匹配
正则表达式匹配
▼ Z算法
Z算法
▼ Tree Data Structure
▼ 广度优先搜索
广度优先搜索
▼ 深度优先搜索
深度优先搜索
▼ 未分类
▼ 最佳买卖股票时机
最佳买卖股票时机
▼ 汉诺塔算法
HanoiTower
▼ 跳跃游戏算法
跳跃游戏
▼ KnightTour
骑士巡逻
▼ N皇后问题
N皇后问题
▼ 雨水收集
雨水收集
▼ 递归楼梯问题
递归楼梯问题
▼ 方阵旋转
方阵旋转
▼ 独特路径
UniquePaths
▼ 数据结构
▼ BloomFilter算法
布隆过滤器
▼ 不相交集数据结构
Disjoint Set
▼ 双向链表
双向链表
▼ Graph
Graph算法
▼ 哈希表
哈希表
▼ Heap数据结构
Heap数据结构
▼ 链表
链表
▼ LRU缓存
LRU缓存
▼ 优先队列
优先队列
▼ 队列
队列
▼ 栈结构
栈结构
▼ Tree Data Structure
树结构
▼ AVL树
AVL树
▼ 二叉搜索树
二叉搜索树
▼ Fenwick树
Fenwick树
▼ 红黑树
红黑树
▼ 线段树
SegmentTree
▼ Trie数据结构
Trie数据结构
N-皇后问题
八皇后问题是在一个8×8
的国际象棋棋盘上放置八枚国际象棋皇后,使得任意两个皇后都不能互相攻击。因此,解决方案要求没有任何两个皇后位于同一行、列或对角线上。八皇后问题是更一般的n皇后问题的一个特例,在一个n×n
的国际象棋棋盘上放置n个非攻击性皇后,对于所有自然数n
都有解,除了n=2
和n=3
。
例如,下面是一个4皇后问题的解决方案。

预期的输出是一个二进制矩阵,其中放置皇后的块用1表示。例如,上面4皇后解决方案的输出矩阵如下:
{ 0, 1, 0, 0}
{ 0, 0, 0, 1}
{ 1, 0, 0, 0}
{ 0, 0, 1, 0}
朴素算法
生成棋盘上所有可能的皇后配置,并打印满足给定约束的配置。
当还有未尝试的配置时
{
生成下一个配置
如果在这个配置中没有皇后冲突,则
{
打印这个配置;
}
}
回溯算法
这个想法是从最左边的列开始,逐列放置皇后。当我们在一个列中放置一个皇后时,我们会检查与已放置的皇后是否有冲突。在当前列中,如果我们找到一个没有冲突的行,我们将标记这个行和列为解决方案的一部分。如果没有找到这样的行,由于冲突,我们将回溯并返回false。
1) 从最左列开始
2) 如果所有皇后都已放置
返回true
3) 尝试当前列的所有行。 对于每个尝试的行:
a) 如果在这个行中可以安全地放置皇后,则将这个[row, column]标记为解决方案的一部分,并递归检查在这里放置皇后是否会导致解决方案。
b) 如果在[row, column]放置皇后会导致解决方案,则返回true。
c) 如果在[row, column]放置皇后不会导致解决方案,则取消标记这个[row, column](回溯)并转到步骤(a)尝试其他行。
3) 如果所有行都已尝试并且没有工作成果,则返回false以触发回溯。
位运算解决方案
位运算算法基本上是这样解决问题的:
- 皇后可以水平、垂直或对角线攻击。因此,每一行只能有一个皇后,每一列也只能有一个皇后,每个对角线上最多只能有一个皇后。
- 由于我们知道每一行只能有一个皇后,我们将从第一行开始,放置一个皇后,然后移动到第二行,放置第二个皇后,依此类推,直到
a) 我们达到一个有效的解决方案,或者
b) 我们到达一个死胡同(即我们不能放置一个皇后,使其免受其他皇后的攻击)。
- 由于我们每次只放置一行皇后,我们不需要担心水平攻击,因为不会有皇后位于同一行上的另一个皇后。
- 这意味着我们只需要在放置某个方格的皇后之前检查三件事情:1) 该方格的列上没有其他皇后,2) 该方格的左对角线上没有其他皇后,以及3) 该方格的右对角线上没有其他皇后。
- 如果我们最终到达一个无法安全放置皇后的地方,我们可以放弃当前的尝试,并立即测试下一个可能性。
首先让我们谈谈递归函数。你会发现它接受3个参数:leftDiagonal
、column
和rightDiagonal
。这些参数在技术上都是整数,但算法利用了一个事实,即一个整数由一系列位表示。所以,将这些参数视为N
位的序列。
每个参数中的每个位代表当前行上相应位置是否“可用”。
例如:
- 对于N=4
,列值为0010
将意味着第三列已经被一个皇后占据。
- 对于N=8
,在第5行的ld值为00011000
将意味着通过该行的第4和第5列的从左上到右下的对角线已经有了皇后。
下面是leftDiagonal
、column
和rightDiagonal
的视觉辅助。

参考资料