问题描述:
n 皇后问题研究的是如何将 n 个皇后放置在 n×n 的棋盘上,并且使皇后彼此之间不能相互攻击。
给定一个整数 n,返回所有不同的 n 皇后问题的解决方案。
每一种解法包含一个明确的 n 皇后问题的棋子放置方案,该方案中 'Q' 和 '.' 分别代表了皇后和空位。
输入: 4
输出: [
[".Q..", // 解法 1
"...Q",
"Q...",
"..Q."],
["..Q.", // 解法 2
"Q...",
"...Q",
".Q.."]
]
解释: 4 皇后问题存在两个不同的解法。
思路:
这道题简单来说,就是深度搜索,但是如果是想要来个最简单的遍历深搜的话,然后一步步判断目前的结果是否满足n皇后的话,一定会超时。所以我们要先理解好n皇后,先摆放的位置怎么去影响下一步摆放的位置选择。
如下图是八皇后,我们逐行进行位置的选择,首先我们第一行选择个‘4’(画的比较丑,就随意接受)
那第二行的时候,不能选的当然就是点(0,4)的正下、左斜下、右斜下,而且移动范围都是1或根号2。然后其他的点我们都可以选。
假设我们第二行选了6,那我们把目前选择的情况用列表写出来就是 [ 4 , 6 ]
我们现在要考虑的是第三行.第三行与第一行的距离是2,所以受到第一行选取的点(4)的影响,其正下、左斜下、右斜下,而且移动范围都是2或2倍根号2,也就是不能选2、4、6。同理,第三行与第二行的距离是1,所以受到第而行选取的点(6)的影响,其正下、左斜下、右斜下,而且移动范围都是1或1倍根号2,也就是不能选5、6、7。那就是说第三行能选择的点就只有0、1、3。
除了这个之外,就是正常深搜罢了,其实这一步就是给深搜树进行一定规则的剪枝。
代码:
class Solution:
def __init__(self):
self.put = []
def kill(self,n,key,ceng):
# n n皇后
# key 目前每一行选择的数字
# ceng 要判断的是第几行
# 告诉你第ceng行可以还选哪些数字 并返回
lo = [1 for i in range(n)]
for i in range(len(key)):
lo[key[i]]=0
if key[i] - (ceng - i)>=0:
lo[key[i] - (ceng - i)] = 0
if key[i] + (ceng - i)<n:
lo[key[i] + (ceng - i)] = 0
res = []
for i in range(n):
if lo[i]==1:
res.append(i)
return res
def show(self,n,key):
# 根据传进来的key(每一行选择的数字)生成字符矩阵格式
di = [['.'for i in range(n)] for j in range(n)]
for i in range(n):
di[i][key[i]]='Q'
res = []
for i in range(n):
a=''
for j in range(n):
a+=di[i][j]
res.append(a)
return res
def shen(self,n,key,ceng):
# 深度搜索
if ceng == n:
# 能够达到层数说明完全符合条件
self.put.append(key)
# 可能的情况+1
return 1
res = 0
# 遍历下一层所有的情况
for i in self.kill(n,key,ceng):
res += self.shen(n,key+[i],ceng+1)
return res
def solveNQueens(self, n):
# res为n皇后的可能情况数,也就是52题的答案
res = self.shen(n,[],0)
put = []
for i in self.put:
put.append(self.show(n,i))
# print(put)
return put
if __name__ == '__main__':
A = Solution()
print(A.solveNQueens(4))