LintCode 33. N皇后问题

题目描述

n皇后问题是将n个皇后放置在n*n的棋盘上,皇后彼此之间不能相互攻击(任意两个皇后不能位于同一行,同一列,同一斜线)。

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

每个解决方案包含一个明确的n皇后放置布局,其中“Q”和“.”分别表示一个女王和一个空位置。


测试样例

输入:1

输出:

  [["Q"]]

输入:4

输出:

[

  // Solution 1

  [".Q..",

  "...Q",

  "Q...",

  "..Q."

  ],

  // Solution 2

  ["..Q.",

  "Q...",

  "...Q",

  ".Q.."

  ]

]


解题思路

使用DFS,每次对每行可用的列进行搜索,并使用一个list记录下对应已使用的列,这里记为used_cols,使用过的列按其所在行的顺序被加入到其中。每次搜索时,先判断下len(used_cols)是否等于n,如果是,则说明每一行都已选择过了,这时候需要生成解决方案,终止搜索。

此题的另一个重点在于对每一行可用的列进行搜索时,怎么判断某一列可用呢?

题目要求是 任意两个皇后不能位于同一行、同一列、同一斜线,对这个规则转换下,对应变为当前搜索的这一列没有被其它行使用过、当前当前行、列的和以及差都没有出现过。


代码

class Solution:

    """

    @param: n: The number of queens

    @return: All distinct solutions

    """

    def solveNQueens(self, n):

        if n == 1:

            return [["Q"]]


        boards = []

        self.dfs(n, [], boards)


        return boards


    def dfs(self, n, used_cols, boards):

        # used_cols里记录的是使用过的列

        # 每行对应有一个

        if len(used_cols) == n:

            boards.append(self.draw(n, used_cols))

            return


        # used_cols的长度可作为当前行数(从0开始)

        cur_row = len(used_cols)


        for col in range(n):

            if not self.is_valid(used_cols, cur_row, col):

                continue


            self.dfs(n, used_cols + [col], boards)


    def draw(self, n, cols):

        board = []


        for col in cols:

            row_str = ''.join(['Q' if c == col else '.' for c in range(n)])

            board.append(row_str)


        return board


    def is_valid(self, used_cols, cur_row, cur_col):

        """检查列数、行列和、行列差有无被使用过"""

        if cur_col in used_cols:

            return False


        for row, col in enumerate(used_cols):

            if cur_row + cur_col == row + col:

                return False


            if cur_row - cur_col == row - col:

                return False


        return True

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。
禁止转载,如需转载请通过简信或评论联系作者。