皇后问题研究的是如何将
个皇后放置在
的棋盘上,并且使皇后彼此之间不能相互攻击。
上图为 皇后问题的一种解法。
给定一个整数 ,返回所有不同的
皇后问题的解决方案。
每一种解法包含一个明确的 皇后问题的棋子放置方案,该方案中
'Q' 和'.' 分别代表了皇后和空位。
示例:
输入: 4
输出: [
[".Q..", // 解法 1
"...Q",
"Q...",
"..Q."],
["..Q.", // 解法 2
"Q...",
"...Q",
".Q.."]
]
解释: 4 皇后问题存在两个不同的解法。
回溯法
思路
皇后问题是对棋盘进行广度优先搜索,先确定每一层落子所在列,排除不可落子列。如果可行保留结果,同时清空选择,如果不可行回溯。
算法
- 初始化三个集合,
cols用来存储列,pie用来存储对角线常数,na用来存储反对角线常数 - 层层递进,排除不可行列,确定当前层落子所在列
- 清空已经选择列
代码实现
/**
* @param {number} n
* @return {string[][]}
*/
var solveNQueens = function(n) {
if (n < 1) return []
let res = []
// 存放列
let cols = new Set()
// 存放对角线常数
let pie = new Set()
// 存放反对角线常数
let na = new Set()
DFS(0, '')
function DFS(row, cur_state) {
// 递归结束条件
// 如果行数大于等于n
if (row >= n) {
// 存结果
res.push(cur_state)
return
}
// 遍历所有可选择列
// 遍历当前行可以落子的所有可选择的列
for (let col = 0; col < n; col++) {
// 选择操作
// 判断当前列如果不能落子,则结束本次循环
if (cols.has(col) || pie.has(col + row) || na.has(col - row)) continue
// 保存选择
cols.add(col)
pie.add(col + row)
na.add(col - row)
// 进入下一层
DFS(row + 1, cur_state + col)
// 清空选择
cols.delete(col)
pie.delete(col + row)
na.delete(col - row)
}
}
// 生成最终结果
return res.map(item => item.split('').map(subItem => '.'.repeat(subItem) + 'Q' + '.'.repeat(n - subItem - 1)))
};