leetcode-52-N皇后②

题目描述:

 

 方法一:回溯

class Solution:
    def totalNQueens(self, n: int) -> int:
        def backtrack(i,tmp,col,z_diagonal,i_diagonal):
            if i == n:
                nonlocal res
                res += 1
                return
            for j in range(n):
                if j not in col and i+j not in z_diagonal and i-j not in i_diagonal:
                    backtrack(i+1,tmp+[s[:j]+"Q"+s[j+1:]],col|{j},z_diagonal|{i+j},i_diagonal|{i-j})
        s = "." * n     
        res = 0
        backtrack(0,[],set(),set(),set())
        return res

另:位运算优化:*

class Solution:
    def totalNQueens(self, n: int) -> int:
        def backtrack(row = 0, hills = 0, next_row = 0, dales = 0, count = 0):
            """
            :type row: 当前放置皇后的行号
            :type hills: 主对角线占据情况 [1 = 被占据,0 = 未被占据]
            :type next_row: 下一行被占据的情况 [1 = 被占据,0 = 未被占据]
            :type dales: 次对角线占据情况 [1 = 被占据,0 = 未被占据]
            :rtype: 所有可行解的个数
            """
            if row == n:  # 如果已经放置了 n 个皇后
                count += 1  # 累加可行解
            else:
                # 当前行可用的列
                # ! 表示 0 和 1 的含义对于变量 hills, next_row and dales的含义是相反的
                # [1 = 未被占据,0 = 被占据]
                free_columns = columns & ~(hills | next_row | dales)
                
                # 找到可以放置下一个皇后的列
                while free_columns:
                    # free_columns 的第一个为 '1' 的位
                    # 在该列我们放置当前皇后
                    curr_column = - free_columns & free_columns
                    
                    # 放置皇后
                    # 并且排除对应的列
                    free_columns ^= curr_column
                    
                    count = backtrack(row + 1, 
                                      (hills | curr_column) << 1, 
                                      next_row | curr_column, 
                                      (dales | curr_column) >> 1, 
                                      count)
            return count

        # 棋盘所有的列都可放置,
        # 即,按位表示为 n 个 '1'
        # bin(cols) = 0b1111 (n = 4), bin(cols) = 0b111 (n = 3)
        # [1 = 可放置]
        columns = (1 << n) - 1
        return backtrack()

另:

class Solution:
    def totalNQueens(self, n: int) -> int:
        def DFS(n: int, row: int, cols: int, left: int, right: int):
            """ 深度优先搜索
            :param n: N皇后个数
            :param row: 递归的深度
            :param cols: 可被攻击的列
            :param left: 左侧斜线上可被攻击的列
            :param right: 右侧斜线上可被攻击的列
            """
            if row >= n:
                self.res += 1
                return

            # 获取当前可用的空间
            bits = (~(cols | left | right)) & ((1 << n) - 1)

            # 遍历可用空间
            while bits:
                # 获取一个位置
                p = bits & -bits
                DFS(n, row + 1, cols | p, (left | p) << 1, (right | p) >> 1)
                bits = bits & (bits - 1)

        if not (n == 1 or n >= 4):
            # N皇后问题只有在 N 大于等于 4 或等于 1 的时候才有解
            return 0
        self.res = 0
        DFS(n, 0, 0, 0, 0)
        return self.res

猜你喜欢

转载自www.cnblogs.com/oldby/p/11700371.html