Отслеживание с возвратом и рекурсия в задаче n ферзей (Python)

Я пишу класс Python, чтобы найти решение проблемы 8 ферзей. Как правильно реализовать обратное отслеживание в моем solve методе? Я думаю, что рекурсия должна работать, однако программа останавливается после того, как решение не найдено с первой попытки, и обратного отслеживания не происходит. Все вспомогательные методы работают правильно.

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()

Моя проблема в отсутствии глубокой копии доски перед добавлением ферзя, или это просто отсутствие отката?


person sucks-at-javascript    schedule 25.11.2019    source источник
comment
Когда я запускаю это, я просто получаю сетку с 2 во всех 64 точках.   -  person Chris    schedule 26.11.2019
comment
Да, это моя проблема - когда доска заполняется при первой попытке найти решение, и ничего не найдено, все клетки закрываются.   -  person sucks-at-javascript    schedule 26.11.2019


Ответы (1)


И то и другое: у вас есть только одна копия доски во всей программе. Вы заполняете его как можно лучше, пока все квадраты не будут заняты или ограничены; поиск не удался, и вы вернетесь из solve. Без механизма сброса платы ваша программа завершается.

Поиск с возвратом упростил бы это за счет нескольких промежуточных плат. Вместо того, чтобы иметь один объект на доске ... сделайте глубокую копию, поместите ферзя, отметьте соответствующие ОГРАНИЧЕННЫЕ квадраты и передайте эту измененную копию на следующий уровень. Если вы вернетесь с ошибкой, позвольте этой копии естественным образом испариться, будучи локальной переменной.

person Prune    schedule 25.11.2019