Leetcode051 n-queens

N皇后

题目描述:

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

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

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

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

示例

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

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

解题思路:

可以创建状态指示元组和使用递归动态规划的方法来进行解题

  • 核心思想是,因为皇后的控制范围为行、列和斜线,因此必定每一个皇后单独占据一行和一列,而我们填入下一个皇后的时候,可以一行一行的填入,但是需要考虑前面已经填入的所有皇后控制的范围,这里通过创建一个状态指示元组,来表示之前皇后所在的行,然后通过循环棋盘列的长度,找到合适的位置。
  • 建立函数queen_pos()来返回所有填入皇后的合适位置,建立函数queen_conflict()来返回当前填入的皇后的一个合适位置
  • queen_pos()中,参数pos为填入的皇后的列的位置,传入queen_conflict()中,并且从状态指示元组state中获得之前已经填入的皇后的坐标,而新填入的皇后的横坐标同之前任一填入皇后的横坐标之差,应该是大于两者的纵坐标之差的因为皇后控制的斜线坐标应该是横纵坐标相等,而新填入的皇后应该在斜线的范围外
  • 直到找到合适的纵坐标以后,将其放入状态元组中,继续递归,最后将所有递归完成的元组,依次填入字符*Q

Python源码:

from typing import List

class Solution:
    def solveNQueens(self, n: int) -> List[List[str]]:
        res = []
        final_ans = []  # 数组储存的是N皇后成功放置后的一个数字组成的元组,各个数字代表各行皇后所在的列数
        ans_list = [-1 for _ in range(n)]  # 标记数组,用来表示该位置上的棋子是否满足条件
        final_ans = list(self.queen_pos(n,final_ans,()))
        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 queen_pos(self, num, final_ans, state=()):
        for pos in range(num):
            # pos指的是皇后当前应该放置的位置的横坐标,也就是列
            if not self.queen_conflict(state, pos):
                # 如果产生皇后的位置信息
                # 如果只剩下最后一个皇后没有放置
                if len(state) == num - 1:
                    yield (pos,)
                # 否则,把当前皇后的位置信息,添加到状态列表里,并且传递给下一个皇后
                # 程序要从前面的皇后得到包含未知信息的元组(元组不可更改)
                # 并且要求后面的皇后提供当前皇后的每一种合法的位置信息
                # 所以把当前皇后的位置信息,添加到状态列表里,并传递给下一个皇后
                else:
                    for result in self.queen_pos(num, final_ans, state + (pos,)):
                        yield (pos,) + result

    def queen_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

        

欢迎关注我的github:https://github.com/UESTCYangHR

你可能感兴趣的:(Leetcode051 n-queens)