题目
设计一种算法,打印 N 皇后在 N × N 棋盘上的各种摆法,其中每个皇后都不同行、不同列,也不在对角线上。这里的“对角线”指的是所有的对角线,不只是平分整个棋盘的那两条对角线。
示例:
输入:4
输出:[[".Q..","...Q","Q...","..Q."],["..Q.","Q...","...Q",".Q.."]]
解释: 4 皇后问题存在如下两个不同的解法。
[
[".Q..", // 解法 1
"...Q",
"Q...",
"..Q."],
["..Q.", // 解法 2
"Q...",
"...Q",
".Q.."]
]
分析: 回溯算法,无非是暴力列举出所有可能,根据条件选择合规的结果,可以想象把棋盘当作一棵树,每一行上面的元素为树中每一层的节点,需要判断的是节点的选择问题,回溯算法的通用框架为:
def backtracking(参数)
if (条件满足):
添加结果
return
for (本层中的节点):
做出选择
路径.add(选择)
backtracking(选择的路径, 选择列表) //递归
回撤选择
本题中,check函数是用来判断是否做出选择,符合条件的结果判定为,棋盘的行数递归到第n层,说明此前每一层均做出了一个符合条件的选择,那么保留当前路径,并return
class Solution:
def solveNQueens(self, n: int):
keep_arr = []
def check(queen_arr, row, col):
for i in range(row+1):
for j in range(n):
if queen_arr[i][j] == 'Q':
if i == row or j == col or (abs(i-row) == abs(j-col)):
return False
return True
def dfs(queen_arr, row):
if row == n:
tmp_arr = []
for arr in queen_arr:
tmp_arr.append(''.join(arr))
keep_arr.append(tmp_arr)
return
for col in range(n):
if not check(queen_arr, row, col):
continue
queen_arr[row][col] = 'Q'
dfs(queen_arr, row+1)
queen_arr[row][col] = '.'
for i in range(n):
queen_arr = [["." for k in range (n)] for m in range (n)]
queen_arr[0][i] = 'Q'
dfs(queen_arr, 1)
return keep_arr