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
:表示棋盘的大小。
迭代法
代码设计
流程图
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 协议 ,转载请注明出处!