N皇后问题
本文最后更新于:2024年3月18日 凌晨
N皇后问题
问题描述
- 在
n x n格的棋盘上防止彼此不受攻击的n个皇后,按照国际象棋的规则,皇后可以攻击与之处在同一行或同一列或同一斜线上的棋子,n后问题等价于在n x n格的棋盘上放置n格皇后,任何2个皇后不放在同一行或同一列或同一斜线上。
算法设计
- 为了判断一个位置所在的列和两条斜线上是否已经有皇后,使用三个集合
columns,diagonals1和diagonals2分别记录每一列以及两个方向的每条斜线上是否有皇后。 - 列的表示法很直观,一共有N 列,每一列的下标范围从0到N−1,使用列的下标即可明确表示每一列。
- 如何表示两个方向的斜线呢?对于每个方向的斜线,需要找到斜线上的每个位置的行下标与列下标之间的关系。
方向一的斜线为从左上到右下方向,同一条斜线上的每个位置满足行下标与列下标之差相等,例如(0,0)和(3,3)在同一条方向一的斜线上,因此使用行下标与列下标之差即可明确表示每一条方向一的斜线。
- 方向二的斜线为从右上到左下方向,同一条斜线上的每个位置满足行下标与列下标之和相等,例如(3,0)和(1,2)在同一条方向二的斜线上,因此使用行下标与列下标之和即可明确表示每一条方向二的斜线。
回溯法
代码实现
流程图

1 | |
backtrack(List<List<String>> solutions, int n, int row, Set<Integer> columns, Set<Integer> diagonals1, Set<Integer> diagonals2):计算第row行可以安置皇后的位置。List<List<String>> solutions:保存所有成功结果的结果集。int n:表示棋盘的大小。int row:表示要计算的行。int[] queens:表示皇后在每一行的位置,a[i]=j,表示第i行的第j列的有皇后。Set<Integer> columns:记录已经被占用的列。Set<Integer> diagonals1:记录已经被占用的左斜线。Set<Integer> diagonals2:记录已经被占用的右斜线。
List<String> generateBoard(int[] queens, int n):通过皇后的位置生成棋盘。int[] queens:表示皇后在每一行的位置,a[i]=j,表示第i行的第j列的有皇后。int n:表示棋盘的大小。
迭代法
代码设计
流程图
.png)
1 | |
static public void Nqueens(int n):计算n后问题。int n:皇后的数量。
static private boolean place(int k):判断皇后的位置是否可行。int k:表示第k行和x[k]列的位置。
本博客所有文章除特别声明外,均采用 CC BY-SA 4.0 协议 ,转载请注明出处!