n 皇后问题研究的是如何将 n 个皇后放置在 n×n 的棋盘上,并且使皇后彼此之间不能相互攻击。
给定一个整数 n,返回所有不同的 n 皇后问题的解决方案。
每一种解法包含一个明确的 n 皇后问题的棋子放置方案,该方案中 ‘Q’ 和 ‘.’ 分别代表了皇后和空位。
示例:
输入: 4
输出: [
[".Q..", // 解法 1
"...Q",
"Q...",
"..Q."],
["..Q.", // 解法 2
"Q...",
"...Q",
".Q.."]
]
解释: 4 皇后问题存在两个不同的解法。
用三个set()记录矩阵内因放入皇后而封住的格子
self.col是列,self.pie是row+col表示的 ‘/’ 方向 self.na是row-col表示的 ‘’ 方向。
参数cur_state的第i个元素表示第i行第cut_state[i]个位置放置皇后
用深度优先搜索方法,逐行递归下去,递归终止条件是行数加到n时,此时即生成了一种解决方案,放入结果数组。
每次递归内,迭代第row行第col列,检查这个点位是否安全,即row和col是否存在于三个set中,安全的话,就把自身攻击范围添加至三个set内,继续下个递归,cur_state.append这一行的列值 col。
递归函数后记得取出放置的皇后,即更新self.col,self.pie,self.na。
class Solution:
import pysnooper
# @pysnooper.snoop()
def solveNQ(self, n):
if n < 1: return []
self.res = []
self.cols,self.pie,self.na = set(),set(),set() # 使用集合来保存皇后攻击范围
self.dfs(n, 0, [])
return self.gen_res(n)
@pysnooper.snoop()
def dfs(self, n, row, cur_state):
if row >= n:
self.res.append(cur_state)
return
for col in range(n):
if col in self.cols or col + row in self.pie or row-col in self.na:
# 若第row行第col列可被攻击到,则退出此次循环,寻找下个可安置皇后的位置
continue
# 若第row行和col列是安全的,则可放置皇后,并添加该皇后的攻击范围
self.cols.add(col)
self.pie.add(row+col)
self.na.add(row-col)
self.dfs(n, row+1, cur_state+[col])
# 继续找下一行可放置皇后的位置
# 按照刚才放置皇后,若不能放置所有的皇后时,需要还原作案现场
self.cols.remove(col)
self.pie.remove(row+col)
self.na.remove(row-col)
# @pysnooper.snoop()
def gen_res(self, n):
board = []
for res in self.res:
for i in res:
board.append('.'*i + 'Q'+ '.'*(n-1-i))
return [board[i:i+n