Leetcode 051 N皇后 python

题目:

皇后问题研究的是如何将 n 个皇后放置在 n×n 的棋盘上,并且使皇后彼此之间不能相互攻击。

上图为 8 皇后问题的一种解法。

给定一个整数 n,返回所有不同的 皇后问题的解决方案。

每一种解法包含一个明确的 n 皇后问题的棋子放置方案,该方案中 'Q''.' 分别代表了皇后和空位。

示例:

输入: 4
输出: [
 [".Q..",  // 解法 1
  "...Q",
  "Q...",
  "..Q."],

 ["..Q.",  // 解法 2
  "Q...",
  "...Q",
  ".Q.."]
]
解释: 4 皇后问题存在两个不同的解法。

思路:

1)需要哪些函数?需要一个函数来判断我们放置当前行的皇后的位置是否冲突,需要一个函数帮助我们递归去放置皇后。

2)用state元组模拟棋盘和皇后的放置情况。我们选一个pos,(从0-num中),判断当前这个pos与之前的放置冲不冲突,不冲突就继续用同样的方法放,冲突的话(所有for选的pos都冲突)就等待for遍历完会自动回到上一层for,会改变上一层的皇后的位置。如果最后一层了我们选的pos还不冲突,证明我们完成了一次解,于是添加到结果中。

3)代码难理解的地方:

a)我们用state构造棋盘,代表皇后的位置,它的长度是逐渐增加的

b)冲突函数我们是对下一次要放进来的皇后的位置作判断,它需要遍历之前所有的皇后位置,看是否处于同一列或对角线上。

c)在for循环中使用递归。于是,我们for的对象就是一个可迭代的很大的生成器,它包含着我们在这个位置取(pos,)后能成功构造棋盘的所有结果。

d)使用yield。yield不同于return, yield后会从上一个yield的位置继续开始,而不是像return一样结束这个函数。

class Solution:
    def solveNQueens(self, n):
        """
        :type n: int
        :rtype: List[List[str]]
        """ 
        res = []
        final_ans = []
        ans_list = [-1 for _ in range(n)]
        final_ans = list(self.queens(n, final_ans, ()))
        #final_ans里储存的是N皇后成功放置后的一个数字组成的元组,各个数字代表各行皇后所在的列数
        for each_ans in final_ans:
            final = []
            for index in each_ans:
                #构建最终答案,成为题目需要的形式
                
                row = '.'*index +'Q'*1 + '.'*(n-index-1)
                final += [row]
            res.append(final)
        return res




    def queens(self, num, final_ans, state = ()):  
        for pos in range(num):
            #pos指的是当前皇后应该放置的横坐标,也就是所在的列。
            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表示当前棋盘构造的长度,也就是下一个皇后应该落在的行的编号
        nextY = len(state)
        for i in range(nextY):
            #遍历之前的行,state[i]表示他们所在的列数,i表示他们所在的行数
            if abs(state[i]-nextX) in (0, nextY-i):
                return True
        return False

猜你喜欢

转载自blog.csdn.net/weixin_41958153/article/details/81096454