Leetcode 51. N 皇后

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

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

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

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

 

示例:

输入:4

输出:[

 [".Q..",  // 解法 1

  "...Q",

  "Q...",

  "..Q."],



 ["..Q.",  // 解法 2

  "Q...",

  "...Q",

  ".Q.."]

]

解释: 4 皇后问题存在两个不同的解法。

 

提示:

  • 皇后彼此不能相互攻击,也就是说:任何两个皇后都不能处于同一条横行、纵行或斜线上。

**难度**: Hard

**标签**: 回溯算法、


# -*- coding: utf-8 -*-
# @Author  : LG

"""
执行用时:76 ms, 在所有 Python3 提交中击败了57.29% 的用户
内存消耗:14.6 MB, 在所有 Python3 提交中击败了5.05% 的用户

解题思路:
    回溯
    具体实现见代码注释
"""
class Solution:
    def solveNQueens(self, n: int) -> List[List[str]]:
        row = []    # 用于保存 不能放置的行,代表此行已有Q,已被使用
        col = []    # 不能放置的列
        obl1 = []   # 不能放置的斜行1
        obl2 = []   # 不能放置的斜行2
        result = [] # 最终结果,保存棋子的存放处
        def solve(r, current):  # 当前行r, 当前已经放置的棋子
            if r == n:          # 如果已经到最后一行,则添加到最终结果中
                result.append(current.copy())
            for j in range(n):  # 遍历列
                if r not in row and j not in col and r-j not in obl1 and r+j not in obl2:   # 放置位置验证
                    row.append(r)   # 放置棋子后,将当前行添加到已使用列表中
                    col.append(j)
                    obl1.append(r-j)
                    obl2.append(r+j)
                    current.append((r,j))   # 添加到当前放置棋子列表中
                    solve(r+1, current)     # 开始下一行

                    row.pop()   # 回溯
                    col.pop()
                    obl1.pop()
                    obl2.pop()
                    current.pop()

        solve(0, [])    # 从第一行开始

        # 将棋子坐标转换到棋盘
        board = [[['.' for _ in range(n)] for _ in range(n)] for _ in range(len(result))]
        for n, rc in enumerate(result):
            for r, c in rc:
                board[n][r][c] = 'Q'
                board[n][r] = ''.join(board[n][r])

        return board