简体   繁体   English

n-皇后问题中的回溯和递归(Python)

[英]Backtracking and recursion in the n-queens problem (Python)

I am writing a python class to find a solution to the 8 queens problem.我正在编写一个 python 类来找到 8 个皇后问题的解决方案。 How can I implement backtracking properly in my solve method?如何在我的solve方法中正确实施回溯? I think the recursion should work, however, the program stops after the solution is not found on the first try, and backtracking does not take place.我认为递归应该可以工作,但是,程序在第一次尝试找不到解决方案后停止,并且不会发生回溯。 All helper methods work properly.所有辅助方法都可以正常工作。

EMPTY = 0
QUEEN = 1
RESTRICTED = 2

class Board:

    # initializes a 8x8 array
    def __init__ (self):
        self.board = [[EMPTY for x in range(8)] for y in range(8)]

    # pretty prints board
    def printBoard(self):
        for row in self.board:
            print(row)

    # places a queen on a board
    def placeQueen(self, x, y):
        # restricts row
        self.board[y] = [RESTRICTED for i in range(8)]

        # restricts column
        for row in self.board:
            row[x] = RESTRICTED

        # places queen
        self.board[y][x] = QUEEN

        self.fillDiagonal(x, y, 0, 0, -1, -1)   # restricts top left diagonal
        self.fillDiagonal(x, y, 7, 0, 1, -1)    # restructs top right diagonal
        self.fillDiagonal(x, y, 0, 7, -1, 1)    # restricts bottom left diagonal
        self.fillDiagonal(x, y, 7, 7, 1, 1)     # restricts bottom right diagonal

    # restricts a diagonal in a specified direction
    def fillDiagonal(self, x, y, xlim, ylim, xadd, yadd):
        if x != xlim and y != ylim:
            self.board[y + yadd][x + xadd] = RESTRICTED
            self.fillDiagonal(x + xadd, y + yadd, xlim, ylim, xadd, yadd)

    # recursively places queens such that no queen shares a row or
    # column with another queen, or in other words, no queen sits on a
    # restricted square. Should solve by backtracking until solution is found.
    def solve(self, queens):
        if queens == 8:
            return True

        for i in range(8):
            if self.board[i][queens] == EMPTY:
                self.placeQueen(queens, i)

                if self.solve(queens - 1):
                    return True

                self.board[i][queens] = RESTRICTED

        return False

b1 = Board()
b1.solve(7)
b1.printBoard()

Is my problem in the lack of a deep copy of the board before adding the queen, or is it just a lack of backtracking?我的问题是在添加皇后之前缺乏对棋盘的深度复制,还是只是缺乏回溯?

It's both: you have only one copy of the board in your entire program.两者兼而有之:在整个程序中,您只有一份电路板副本。 You fill it as best you can, until all squares are occupied or restricted;你尽你所能填满它,直到所有的方格都被占用或限制; the search fails, and you return from solve .搜索失败,您从solve返回。 With no mechanism to reset the board, your program ends.由于没有重置电路板的机制,您的程序将结束。

Backtracking would make this simple, at the cost of multiple intermediate boards.回溯将使这变得简单,代价是多个中间板。 Instead of having a single board object ... make a deep copy, place the queen, mark the appropriate RESTRICTED squares, and pass that altered copy to the next level.而不是有一个单一的棋盘对象......制作一个深层副本,放置皇后,标记适当的受限方块,并将修改后的副本传递到下一个级别。 If you return with failure, let that copy evaporate naturally, being a local variable.如果失败返回,让该副本自然蒸发,成为局部变量。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM