n 皇后问题研究的是如何将 n 个皇后放置在 n×n 的棋盘上,并且使皇后彼此之间不能相互攻击。
上图为 8 皇后问题的一种解法。
给定一个整数 n,返回 n 皇后不同的解决方案的数量。
示例:
输入: 4 输出: 2 解释: 4 皇后问题存在如下两个不同的解法。 [ [".Q..", // 解法 1 "...Q", "Q...", "..Q."], ["..Q.", // 解法 2 "Q...", "...Q", ".Q.."] ]
首先先来吐槽下题目,根本没有创新。试问如果上一道题都做出来了,这道题不是更简单吗?两者考察的逻辑是完全一样的。
想要AC这道题,只需要返回的时候返回我们的储存答案的列表的长度即可。
class Solution:
def totalNQueens(self, n):
"""
:type n: int
:rtype: List[List[str]]
"""
final_ans = []
final_ans = list(self.queens(n, final_ans, ()))
return len(final_ans)
def queens(self, num, final_ans, state = ()):
for pos in range(num):
if not self.conflict(state, pos):
#产生当前皇后的位置信息
#如果只剩一个皇后没有放置
if len(state) == num-1:
yield (pos,)
#否则,把当前皇后的位置信息,添加到状态列表里,并传递给下一皇后。
#程序要从前面的皇后得到包含位置信息的元组(元组不可更改)
#并要为后面的皇后提供当前皇后的每一种合法的位置信息
#所以把当前皇后的位置信息,添加到状态列表里,并传递给下一皇后。
else:
for result in self.queens(num, final_ans, state+(pos,)):
yield (pos, ) + result
def conflict(self, state, nextX):
nextY = len(state)
for i in range(nextY):
if abs(state[i]-nextX) in (0, nextY-i):
return True
return False
但是,我还是决定写点思路,与上一篇大致相同,稍稍修改
思路:
1)需要哪些函数?需要一个函数来判断我们放置当前行的皇后的位置是否冲突,需要一个函数帮助我们递归去放置皇后。
2)用state元组模拟棋盘和皇后的放置情况。我们选一个pos,(从0-num中),判断当前这个pos与之前的放置冲不冲突,不冲突就继续用同样的方法放(用for 去遍历每个可选的位置),冲突的话(所有for选的pos都冲突)就等待for遍历完会自动回到上一层for,会改变上一层的皇后的位置。如果最后一层了我们选的pos还不冲突,证明我们完成了一次解,于是添加到结果中。
3)代码难理解的地方:
a)我们用state构造棋盘,代表皇后的位置,它的长度是逐渐增加的
b)冲突函数我们是对下一次要放进来的皇后的位置作判断,它需要遍历之前所有的皇后位置,看是否处于同一列或对角线上。
c)在for循环中使用递归。于是,我们for的对象就是一个可迭代的很大的生成器,它包含着我们在这个位置取(pos,)后能成功构造棋盘的所有结果。
d)使用yield。yield不同于return, yield后会从上一个yield的位置继续开始,而不是像return一样结束这个函数。
e)当我们for循环的那个递归函数返回不了任何东西的时候,意思是我们之前取的位置不正确,这时候for循环不会进行,因为你不能for in 一个空的生成器,接着会跳到开头尝试下一个不冲突的pos能不能找到解。