N-Königin backtracking in Python: wie die Rückkehr Lösungen, anstatt Sie zu drucken?

def solve(n):
    #prepare a board
    board = [[0 for x in range(n)] for x in range(n)]
    #set initial positions
    place_queen(board, 0, 0)

def place_queen(board, row, column):
    """place a queen that satisfies all the conditions"""
    #base case
    if row > len(board)-1:
        print board
    #check every column of the current row if its safe to place a queen
    while column < len(board):
        if is_safe(board, row, column):
            #place a queen
            board[row][column] = 1
            #place the next queen with an updated board
            return place_queen(board, row+1, 0)
        else:
            column += 1
    #there is no column that satisfies the conditions. Backtrack
    for c in range(len(board)):
        if board[row-1][c] == 1:
            #remove this queen
            board[row-1][c] = 0
            #go back to the previous row and start from the last unchecked column
            return place_queen(board, row-1, c+1)

def is_safe(board, row, column):
    """ if no other queens threaten a queen at (row, queen) return True """
    queens = []
    for r in range(len(board)):
        for c in range(len(board)):
            if board[r][c] == 1:
                queen = (r,c)
                queens.append(queen)
    for queen in queens:
        qr, qc = queen
        #check if the pos is in the same column or row
        if row == qr or column == qc:
            return False
        #check diagonals
        if (row + column) == (qr+qc) or (column-row) == (qc-qr):
            return False
    return True

solve(4)

Schrieb ich Python-code für N-queen problem, und es gibt jede mögliche Lösung, wenn es gefunden wird. Jedoch möchte ich diesen code ändern, so dass es gibt eine Liste mit allen Lösungen(board-Konfigurationen), anstatt Sie zu drucken. Ich habe versucht, ändern Sie den code wie folgt:

def solve(n):
    #prepare a board
    board = [[0 for x in range(n)] for x in range(n)]
    #set initial positions
    solutions = []
    place_queen(board, 0, 0, solutions)

def place_queen(board, row, column, solutions):
    """place a queen that satisfies all the conditions"""
    #base case
    if row > len(board)-1:
        solutions.append(board)
        return solutions
    #check every column of the current row if its safe to place a queen
    while column < len(board):
        if is_safe(board, row, column):
            #place a queen
            board[row][column] = 1
            #place the next queen with an updated board
            return place_queen(board, row+1, 0, solutions)
        else:
            column += 1
    #there is no column that satisfies the conditions. Backtrack
    for c in range(len(board)):
        if board[row-1][c] == 1:
            #remove this queen
            board[row-1][c] = 0
            #go back to the previous row and start from the last unchecked column
            return place_queen(board, row-1, c+1, solutions)

Jedoch zurück, sobald die erste Lösung gefunden wird, so solutions nur darin besteht, eine mögliche board-Konfiguration. Da print vs. return wurde verwirrend für mich für backtracking-algorithmen, ich würde es sehr begrüßen, wenn jemand könnte mir zeigen, wie ändern Sie den obigen code, und der Umgang mit ähnlichen Problemen in der Zukunft.

Ich nehme an, mit einer globalen Variablen arbeiten würde, aber ich habe von irgendwo, dass die Verwendung von globalen Variablen für ein solches problem ist entmutigt. Könnte mir jemand erklären, dieses auch?

EDIT:

def solve(n):
    #prepare a board
    board = [[0 for x in range(n)] for x in range(n)]
    #set initial positions
    solutions = list()
    place_queen(board, 0, 0, solutions)
    return solutions

def place_queen(board, row, column, solutions):
    """place a queen that satisfies all the conditions"""
    #base case
    if row > len(board)-1:
        #print board
        solutions.append(deepcopy(board)) #Q1
    #check every column of the current row if its safe to place a queen
    while column < len(board):
        if is_safe(board, row, column):
            #place a queen
            board[row][column] = 1
            #place the next queen with an updated board
            return place_queen(board, row+1, 0, solutions) #Q2
        else:
            column += 1
    #there is no column that satisfies the conditions. Backtrack
    for c in range(len(board)):
        if board[row-1][c] == 1:
            #remove this queen
            board[row-1][c] = 0
            #go back to the previous row and start from the last unchecked column
            return place_queen(board, row-1, c+1, solutions) #Q3

Den oben genannten gibt alle Lösungen gefunden, statt Sie zu drucken. Ich habe ein paar mehr Fragen (sicherheitsbezogene Teile markiert sind Q1 und Q2 im obigen code)

  1. Warum müssen wir solutions.append(deepcopy(board))? In anderen Worten, was genau passiert, wenn wir tun solutions.append(board) und warum führt das zum anfügen der ersten board, die [[0,0,0,0] ...]?
  2. Warum laufen wir in ein problem, wenn return place_queen(board, row+1, 0) wird ersetzt durch place_queen(board, row+1, 0)? Sind wir nicht tatsächlich wieder etwas (oder None), aber ohne return die Liste geht aus dem index.
  • Wo sind Sie, Druck Sie in die erste snippet?
  • print board wenn die aktuelle Zeile überschritten hat, die Größe der Leiterplatte
  • Zur Beantwortung Ihrer global sub-Frage: c2.com/cgi/wiki?GlobalVariablesAreBad
  • Und print vs. return: stackoverflow.com/questions/7664779/... (bitte nicht mehrere Fragen in einem post, vor allem, wenn man ein Duplikat).
  • Danke für den link @jonrsharpe aber ich fürchte, das ist nicht das, was ich fordere. Der Unterschied zwischen print und return ist ziemlich klar. Was war ärgerlich, mir ist, wenn ich kann leicht drucken Sie das Ergebnis erwartet man von einem, ich habe eine harte Zeit versucht, herauszufinden, wie die Rückgabe einer Reihe von erwarteten Ergebnissen.
InformationsquelleAutor Maximus S | 2013-12-11
Schreibe einen Kommentar