Может кто-нибудь помочь объяснить рекурсию в этом алгоритме обратного отслеживания? - PullRequest
0 голосов
/ 17 февраля 2020

Это программа, которая решает доску судоку с использованием python и алгоритма обратного слежения, но я, кажется, не понимаю рекурсию в execute (bo). Похоже, что если условие не выполнено, то индекс сбрасывается до 0, и он продолжает пробовать числа в одной и той же позиции.

Может кто-нибудь помочь объяснить более простыми словами, как функция отслеживает и перепроверяет условия?

board = [
    [7,8,0,4,0,0,1,2,0],
    [6,0,0,0,7,5,0,0,9],
    [0,0,0,6,0,1,0,7,8],
    [0,0,7,0,4,0,2,6,0],
    [0,0,1,0,5,0,9,3,0],
    [9,0,4,0,6,0,0,0,5],
    [0,7,0,3,0,0,0,1,2],
    [1,2,0,0,0,7,4,0,0],
    [0,4,9,2,0,6,0,0,7]
]


def solve(bo):
    find = find_empty(bo)
    if not find:
        return True
    else:
        row, col = find

    for i in range(1,10):
        if valid(bo, i, (row, col)):
            bo[row][col] = i

            if solve(bo):
                return True

            bo[row][col] = 0

    return False


def valid(bo, num, pos):
    # Check row
    for i in range(len(bo[0])):
        if bo[pos[0]][i] == num and pos[1] != i:
            return False

    # Check column
    for i in range(len(bo)):
        if bo[i][pos[1]] == num and pos[0] != i:
            return False

    # Check box
    box_x = pos[1] // 3
    box_y = pos[0] // 3

    for i in range(box_y*3, box_y*3 + 3):
        for j in range(box_x * 3, box_x*3 + 3):
            if bo[i][j] == num and (i,j) != pos:
                return False

    return True


def print_board(bo):
    for i in range(len(bo)):
        if i % 3 == 0 and i != 0:
            print("- - - - - - - - - - - - - ")

        for j in range(len(bo[0])):
            if j % 3 == 0 and j != 0:
                print(" | ", end="")

            if j == 8:
                print(bo[i][j])
            else:
                print(str(bo[i][j]) + " ", end="")


def find_empty(bo):
    for i in range(len(bo)):
        for j in range(len(bo[0])):
            if bo[i][j] == 0:
                return (i, j)  # row, col

    return None

print_board(board)
solve(board)
print("___________________")
print_board(board)

1 Ответ

0 голосов
/ 17 февраля 2020

Правильно! Таким образом, способ, которым работает это решение, заключается в том, что он находит следующее пустое поле на доске, пытается вставить число из диапазона 1..9 и затем проверяет правильность. Проверка достоверности - это предварительный ответ на вопрос, является ли данное число правильным, т. Е. Не вызывает ли оно нарушения правил. Если это так, число вставляется в массив и solve вызывается рекурсивно. Теперь здесь происходит скрытое возвращение. Если этот рекурсивный вызов solve не может дать полностью непротиворечивого решения головоломки, тогда вся «ветвь», начиная с нашего предварительного предположения, удаляется из стека вызовов, сбойное предположение сбрасывается на доске (удаляется), и мы продолжаем следующее предположение.

...