51N皇后

题目:皇后问题研究的是如何将 n 个皇后放置在 n×n 的棋盘上,并且使皇后彼此之间不能相互攻击。给定一个整数 n,返回所有不同的 n 皇后问题的解决方案。每一种解法包含一个明确的 n 皇后问题的棋子放置方案,该方案中 'Q' 和 '.' 分别代表了皇后和空位。
来源:https://leetcode-cn.com/problems/n-queens/

法一: 自己的代码   时间超过了百分之90

思路: 参照官方的解法,用处理list的回溯框架实现了一遍,关键是要满足题中的四个条件,水平的是用for循环遍历的,不会出现重复,两个斜向的用p和q来实现,竖直方向用cols来记录,这四个条件实际上就是剪枝条件.

class Solution:
    def solveNQueens(self, n: int):
        results = []
        def backtrack(row=-1,col=0):
            # 回溯终止条件,如果到最后一行了,说明找到一个解了,存储
            if row == n-1:
                solution = []
                for _, col in sorted(queens):
                    solution.append('.' * col + 'Q' + '.' * (n - col - 1))
                results.append(solution)
                return
            row += 1
            for col in range(n):
                # 如果等于0,说明可以放,
                # if这儿就是剪枝条件
                if cols[col] + p[col+row] + q[col-row] == 0:
                    # 放置一个皇后
                    queens.add((row,col))
                    # 这里cols的作用实际上是为了记录竖直方向上是否偶皇后,
                    # p,q为了记录两个斜方向上是否有皇后
                    # 水平方向用for循环遍历,每次回溯结束后就置0,所以一定没有皇后
                    # 且由于这些都是可变对象,回溯函数每次调用结束后,值更改后的值仍然存在,故需要回溯函数后面加上置0的程序
                    # 而 row 和 col是不变对象,回溯函数每次调用结束后,会恢复调用前的值
                    cols[col] = 1
                    p[col+row] = 1
                    q[col-row] = 1
                    backtrack(row,col)
                    # 回溯函数结束后,取出刚才放的皇后,继续for循环,判断下一个位置
                    queens.remove((row,col))
                    cols[col] = 0
                    p[col + row] = 0
                    q[col - row] = 0
        cols = [0] * n
        # p记录主对角线方向的,q记录副对角线方向的
        # p,q是通过画图观察出来的,引入p,q是为了区分放置皇后后斜线方向上不能再放置皇后
        p = [0] * (2*n - 1)
        q = [0] * (2*n - 1)
        # 因为list不能append pop 元组,故这里用set
        queens = set()
        backtrack()
        return results
if __name__ == '__main__':
    duixiang = Solution()
    ww = duixiang.solveNQueens(4)
    print('结果是:', ww)
View Code

法二: 官方的解法,思路非常清晰用了多个函数实现了模块化

# 官网python代码
class Solution:
    def solveNQueens(self, n: int):
        def could_place(row, col):
            return not (cols[col] + hill_diagonals[row - col] + dale_diagonals[row + col])
        def place_queen(row, col):
            queens.add((row, col))
            cols[col] = 1
            hill_diagonals[row - col] = 1
            dale_diagonals[row + col] = 1
        def remove_queen(row, col):
            queens.remove((row, col))
            cols[col] = 0
            hill_diagonals[row - col] = 0
            dale_diagonals[row + col] = 0
        def add_solution():
            solution = []
            for _, col in sorted(queens):
                solution.append('.' * col + 'Q' + '.' * (n - col - 1))
            output.append(solution)
        def backtrack(row=0):
            for col in range(n):
                if could_place(row, col):
                    place_queen(row, col)
                    if row + 1 == n:
                        add_solution()
                    else:
                        backtrack(row + 1)
                    # 执行这个的目的是回溯函数结束时,返回调用前的状态
                    remove_queen(row, col)
        cols = [0] * n
        hill_diagonals = [0] * (2 * n - 1)
        dale_diagonals = [0] * (2 * n - 1)
        queens = set()
        output = []
        backtrack()
        return output
if __name__ == '__main__':
    duixiang = Solution()
    ww = duixiang.solveNQueens(4)
    print('结果是:', ww)
View Code

 

posted on 2019-12-01 22:32  吃我一枪  阅读(208)  评论(0编辑  收藏  举报

导航