n皇后回溯迭代所有位置

时间:2017-02-09 19:16:49

标签: algorithm python-3.x n-queens

我试图在没有任何第三方库的情况下解决n Queen问题。所以我只使用普通的python数组和循环。这里有nQueen函数

 def nQueenBackTrack(self, row, n):
        for i in range(n):
            if self.isTheQueenSafe(row , i):
                print(row,i)
                self.board[row][i] = "Q"
                self.print_the_board()
                if row == n:
                    self.print_the_board()
                else:
                    self.nQueenBackTrack(row + 1, n)
很直接。现在,对于我的isQueenSafe函数,我检查来自其他皇后的水平和对角线攻击。

def isTheQueenSafe(self, row,col):
        for i in range(self.N):
            # check horizontal Queens
            if self.does_board_has_a_queen_at(row,i) or self.does_board_has_a_queen_at(i, col):
                return False
            # check diagonal Queens
            s = row + col
            k = row - col
            for x in range(self.N):
                for y in range(self.N):
                    if x + y == s and self.board[x][y] == "Q":
                        return False
                    if x - y == k and self.board[x][y] == "Q":
                        return False

这是我遇到问题的功能。我相信我是在正确检查条件。我把它作为4 x 4板的输出。

['Q', '.', '.', '.'] 

['.', '.', 'Q', '.'] 

['.', '.', '.', '.'] 

['.', '.', '.', '.']

有人可以指出我正确的方向

2 个答案:

答案 0 :(得分:1)

当你不能把女王放在任何地方时,你不处理这个案子。

让我们思考一下:

  • 你打电话给你的功能,你把第一个女王放在(0,0)
  • 女王被安置因为你可以
  • 您不在最后一行,因此您输入递归以将女王放入下一行
  • 你试图将女王放在(0,1)的第二行,然后是(1,1)这两个都不可能。
  • 然后尝试将其放在(2,1)成功,这样就可以进入递归的第三级
  • 你现在不能把女王放在那一行的任何地方。
  • 你没有放置女王
  • 就到达了阵列的末尾
  • 递归返回第二行
  • 然后你(可能)甚至尝试将另一位女王放在第二排,但你不能。到达第二行的末尾,此递归调用也返回
  • 然后你(可能)甚至尝试在第一排放另一位女王,但你又不能。到达第一行的末尾,第一次调用nQueenBackTrack返回。
  • 程序终止时只有两个皇后放置在您可以在输出中看到的那些位置。

我建议你调试你的程序调试(Python debugging tips),或者你也可以添加一些额外的打印语句(例如在进入和从方法调用返回之前),这样你就可以真正看到发生了什么

我假设有些东西:

  • 我假设您在打印时已经旋转了电路板,因为...通常x是列,y是行。 x在水平方向上,y在垂直方向上。
  • 我还假设您确实正确实施了isTheQueenSafe - 方法。您在评论中提到您实际上在某个时候返回true
  • 我假设您的nQueenBackTrack方法中没有更多代码。

答案 1 :(得分:1)

回溯算法需要能够撤消对游戏状态所做的更改。在您的代码的情况下,它应该在找到有效位置时删除它所放置的女王:

def nQueenBackTrack(self, row, n):
    for i in range(n):
        if self.isTheQueenSafe(row , i):
            self.board[row][i] = "Q"  # this will need to be reversed later
            if row == n:
                self.print_the_board()
            else:
                self.nQueenBackTrack(row + 1, n)
            self.board[row][i] = "."  # backtrack: reset the modified square

此代码应打印出所有解决方案,但最后会将电路板留空。如果您只想打印您可以找到的第一个解决方案(并让电路板上有皇后),您需要将函数更改为return一个值,表明是否找到了解决方案。然后递归代码可以传递成功报告,或者如果递归失败则回溯:

def nQueenBackTrack(self, row, n):
    for i in range(n):
        if self.isTheQueenSafe(row , i):
            self.board[row][i] = "Q"
            if row == n:
                self.print_the_board()
                return True               # success!
            result = self.nQueenBackTrack(row + 1, n)
            if result:
                return True               # pass on report of success
            self.board[row][i] = "."      # otherwise, backtrack
    return False                          # if no solution was found, report failure