首页

▼ 算法合集

▼ 加密算法

▼ 凯撒密码

凯撒密码

▼ 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=2n=3

例如,下面是一个4皇后问题的解决方案。

N皇后

预期的输出是一个二进制矩阵,其中放置皇后的块用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个参数:leftDiagonalcolumnrightDiagonal。这些参数在技术上都是整数,但算法利用了一个事实,即一个整数由一系列位表示。所以,将这些参数视为N位的序列。

每个参数中的每个位代表当前行上相应位置是否“可用”。

例如: - 对于N=4,列值为0010将意味着第三列已经被一个皇后占据。 - 对于N=8,在第5行的ld值为00011000将意味着通过该行的第4和第5列的从左上到右下的对角线已经有了皇后。

下面是leftDiagonalcolumnrightDiagonal的视觉辅助。

leftDiagonal

参考资料