簡體   English   中英

所有可能的N-皇后

[英]All possible N-Queens

經典的N皇后問題找到了一種方法,可以將n個皇后放置在n×n棋盤上,這樣就不會有兩個皇后互相攻擊。 這是我對N皇后問題的解決方案。

class Solution(object):
    def solveNQueens(self, n):
        """
        :type n: int
        :rtype: List[List[str]]
        """
        grid = [['.' for _ in range(n)] for _ in range(n)]
        solved = self.helper(n, 0, grid)
        if solved:
            return ["".join(item) for item in grid]
        else:
            return None

    def helper(self, n, row, grid):
        if n == row:
            return True
        for col in range(n):
            if self.is_safe(row, col, grid):
                grid[row][col] = 'Q'
                if self.helper(n, row + 1, grid):
                    return True
                else:
                    grid[row][col] = '.'
        return False

    def is_safe(self, row, col, board):
        for i in range(len(board)):
            if board[row][i] == 'Q' or board[i][col] == 'Q':
                return False
        i = 0
        while row - i >= 0 and col - i >= 0:
            if board[row - i][col - i] == 'Q':
                return False
            i += 1
        i = 0
        while row + i < len(board) and col + i < len(board):
            if board[row + i][col - i] == 'Q':
                return False
            i += 1
        i = 1
        while row + i < len(board) and col - i >= 0:
            if board[row + i][col - i] == 'Q':
                return False
            i += 1
        i = 1
        while row - i >= 0 and col + i < len(board):
            if board[row - i][col + i] == 'Q':
                return False
            i += 1
        return True


if __name__ == '__main__':
    solution = Solution()
    print(solution.solveNQueens(8))

對該問題的擴展指出,找到所有可能的解決方案,然后以列表形式返回。 我試圖通過向helper方法添加列變量來擴展我的解決方案,該變量從0開始,以跟蹤一個完整的解決方案和下一個完整的解決方案的開始。 因此,基本情況變為

if row == n and col == n:
   return True

但是這種方法不起作用,因為每個連續的遞歸調用最終都在錯誤的列中結束。 有人可以幫助擴展此解決方案以找到所有可能的解決方案。

好問題! N-queens也是一個很大的遞歸問題:)實際上,您實際上已經很接近想要的東西了,您不必修改太多代碼。

進行思考的一種好方法是了解您正在研究的兩個不同問題。 您當前的方法是使用回溯來找到第一個可能的解決方案 您要做的就是找到所有解決方案 ,這是一個類似的問題,只需要您對基本情況進行不同的考慮即可。

在當前設置中,如果基本情況返回True,則父調用將短路並返回True。 當嘗試查找任何單個解決方案時,這是理想的選擇,因為一旦找到可行的解決方案,我們就知道可以停止尋找。 但是,因此,我們不會繼續探索其他途徑。

思考回溯的一種方法是,您基本上是在創建可能的棋盤樹,這些棋盤可能來自可能的移動。 為了找到第一個解決方案,一旦您到達葉子節點或獲勝狀態,便會一直返回。 但是,您要做的是繼續遍歷樹的所有其他路徑,並繼續尋找葉子獲勝狀態並記錄整個過程。

因此,一種修改當前方法的簡單方法是修改基本情況,以使其不返回True,而是在跟蹤所有解決方案的變量中記錄董事會狀態(獲勝狀態)。 另外,現在在遞歸的情況下,當您進行遞歸調用時,您無需檢查它是否返回True或False,而是繼續在for循環中嘗試並嘗試所有動作。

我像這樣修改了您的解決方案,然后得到了92個解決方案,互聯網證實了這一點是真的:)

class Solution(object):
    def __init__(self):
        self.solutions = []

    def solveNQueens(self, n):
        """
        :type n: int
        :rtype: List[List[str]]
        """
        grid = [['.' for _ in range(n)] for _ in range(n)]
        solved = self.helper(n, 0, grid)
        print len(self.solutions)
        if solved:
            return ["".join(item) for item in grid]
        else:
            return None

    def helper(self, n, row, grid):
        if n == row:
            print "wooo"
            self.solutions.append(copy.deepcopy(grid))
            return
        for col in range(n):
            if self.is_safe(row, col, grid):
                grid[row][col] = 'Q'
                self.helper(n, row + 1, grid)
                grid[row][col] = '.'

我希望這有幫助!

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM