一、题目
n 皇后问题研究的是如何将 n 个皇后放置在 n×n 的棋盘上,并且使皇后彼此之间不能相互攻击。
上图为 8 皇后问题的一种解法。
给定一个整数 n,返回所有不同的 n 皇后问题的解决方案。 每一种解法包含一个明确的 n 皇后问题的棋子放置方案,该方案中 ‘Q’ 和 ‘.’ 分别代表了皇后和空位。
示例:
输入:4
输出:[
[".Q..", // 解法 1
"...Q",
"Q...",
"..Q."],
["..Q.", // 解法 2
"Q...",
"...Q",
".Q.."]
]
解释: 4 皇后问题存在两个不同的解法。
提示:
- 皇后彼此不能相互攻击,也就是说:任何两个皇后都不能处于同一条横行、纵行或斜线上。
二、解决
1、DFS
版本1
思路:
给定一个N*N方格Grid,从Grid[0,0]开始,逐行向下扫描,若一行中某个格子存在合法的位置,记录下来,然后继续往下扫描。
中间有不合法格子则中断,回到上一层的后一个格子,然后再逐层往下扫描,扫描到最后一行后,若存在合法的位置,则记录下来。
下面是一个4*4的回溯状态树,来自参考5,具体回溯过程可以观看其中的视频,比较详细。
代码:
public List<List<String>> solveNQueens(int n) {
List<List<String>> res = new LinkedList<List<String>>();
int[] usedCols = new int[n];// usedCols[i]: Column of the queen in row i
Arrays.fill(usedCols, -1); // 数组usedCols每个元素都填上-1
DFS(usedCols, 0, res);
return res;
}
void DFS(int[] usedCols, int row, List<List<String>> res) {
int n = usedCols.length;
if (row == n) {
res.add(drawGrids(usedCols));
return;
}
// 扫描当前行的每一列
for (int col = 0; col < n; col++) {
// 对该格进行判断,有效则记录并继续扫描下一行
if (isValid(usedCols, row, col)) {
usedCols[row] = col;
DFS(usedCols, row + 1, res);// Move on to the next row
}
}