【问题标题】:NQueens - Recursive BackTracking QuestionNQueens - 递归回溯问题
【发布时间】:2021-02-25 19:23:26
【问题描述】:

我目前正在使用 Python 学习 BackTracking 算法,每个人通常首先会问的第一个问题是 NQueens。 NQueens 是你拿一块大小为 N x N 的棋盘的地方,你必须确定在哪里放置 N 个皇后,这样它们就不会受到任何其他皇后的攻击。

例子:

N = 5

['Q', 0, 0, 0, 0]

[0, 0, 'Q', 0, 0]

[0, 0, 0, 0, 'Q']

[0, 'Q', 0, 0, 0]

[0, 0, 0, 'Q', 0]

目前,我的算法返回所有可能的解决方案。我如何产生一个结果。例如,当 N = 8 时,有 92 个最佳结果,我如何只返回一个结果而不是打印 92 个单独的结果。

#This is our main recursive function that will determine optimal outcome
def NQueens(row,Current,N):
    #this tells us when to stop
    if row == N:
        print("\n")
        return printBoard(Current) 
    
    for choice in range(0,N):
        if isValid(row,choice,Current,N):
            #Place Queen in appropriate spot
            Current[row][choice] = "Q"
            
            #Go to next row
            NQueens(row+1,Current,N)
        Current[row][choice] = 0
    return "All Solutions Found"

#This function determines whether we can put a Queen in a certain orientation on the board
def isValid(row,col,Current,N):
    #check whether current state of game has queen in row/column
    for i in range(0,N):
        #checks column/row and sees whether a queen exists already
        if Current[row][i] == "Q" or Current[i][col] == "Q":
            return False
    
    # Check upper diagonal on right side 
    i = row-1
    j = col + 1
    
    #Do while row is greater than 0 and column is less than N
    while i >= 0 and j < N:
        if Current[i][j] == "Q":
            return False
        i -= 1
        j += 1
       
    # Check upper diagonal on left side
    #Do while row is greater than 0 and column is greater than N
    i = row-1
    j = col - 1
    while i >= 0 and j >= 0:
        if Current[i][j] == "Q":
            return False
        i -= 1
        j -= 1
    #If we pass the diagonal/row/column tests, we can then determine this is a valid move
    return True

###############################################################################################################
#These functions deal with board creation and printing them in a proper format
def generateBoard(N):
    #generate board based on User Input N in Main()
    Board = [[0 for i in range(0,N)] for j in range(0,N)]
    return Board

def printBoard(arr):
    #Loop through each row to print an organized board
    for row in arr:
        print(row)

def main():
    #ask number from user
    print("What sized board would you like?"
    " Please input a number higher that 3: ")

    #user input used to determine size of board
    N = int(input())

    #generate Board that will be used
    Board = generateBoard(N)

    #this is the current status of the board
    printBoard(Board)
    print("\n")

    #Runs Algorithm
    print(NQueens(0,Board,N))
    

if __name__ == "__main__":
    main()

【问题讨论】:

    标签: python recursion backtracking n-queens


    【解决方案1】:

    NQueens 需要与其调用者沟通已找到解决方案;如果是这样的话,一个简单的return True 就可以了。我对您的代码进行了以下更改(您之前的行已被注释):

    def NQueens(row,Current,N):
        #this tells us when to stop
        if row == N:
            print("\n")
            #return printBoard(Current) 
            return True  # found a solution, say so
    
        for choice in range(0,N):
            if isValid(row,choice,Current,N):
                #Place Queen in appropriate spot
                Current[row][choice] = "Q"
            
                #Go to next row
                # NQueens(row+1,Current,N)
                if NQueens(row+1,Current,N):  # recursive call found a solution, let's stop
                    return True
            Current[row][choice] = 0
        #return "All Solutions Found" 
    

    main():

    # ...
    #Runs Algorithm
    #print(NQueens(0,Board,N))
    if NQueens(0,Board,N):
        printBoard(Board)  # found a solution, print it
    

    【讨论】:

    • 太棒了,谢谢你的帮助!
    【解决方案2】:

    我已修复您的代码以使其具有良好的性能: 我将这段代码https://www.geeksforgeeks.org/n-queen-problem-backtracking-3/ 和你的代码合并得到它。

    count = 1
    
    def printOut(arrayMap):
        global count
        print('{}: -'.format(count))
        count += 1
        for i in range(0, len(arrayMap)):
            print(arrayMap[i])
    
    
    # This is our main recursive function that will determine optimal outcome
    def NQueens(currentRow, arrayMap, matrixSize):
        # this tells us when to stop
        if currentRow == matrixSize:
            print()
            printOut(arrayMap)
            return True  # found a solution, say so
    
        res = False
        for col in range(0, matrixSize):
            if isValid(currentRow, col, arrayMap, matrixSize):
                # Place Queen in appropriate spot
                arrayMap[currentRow][col] = 0
    
                # Go to next row
                # NQueens(row+1,Current,N)
                res = NQueens(currentRow + 1, arrayMap, matrixSize) or res # recursive call found a solution, let's stop
    
                arrayMap[currentRow][col] = 1
        # return "All Solutions Found"
        return res
    
    
    # This function determines whether we can put a Queen in a certain orientation on the board
    def isValid(row, col, arrayMap, matrixSize):
        # check whether current state of game has queen in row/column
        for i in range(0, matrixSize):
            # checks column/row and sees whether a queen exists already
            if arrayMap[row][i] == 0 or arrayMap[i][col] == 0:
                return False
    
        # Check upper diagonal on right side
        i = row - 1
        j = col + 1
    
        # Do while row is greater than 0 and column is less than N
        while i >= 0 and j < matrixSize:
            if arrayMap[i][j] == 0:
                return False
            i -= 1
            j += 1
    
        # Check upper diagonal on left side
        # Do while row is greater than 0 and column is greater than N
        i = row - 1
        j = col - 1
        while i >= 0 and j >= 0:
            if arrayMap[i][j] == 0:
                return False
            i -= 1
            j -= 1
        # If we pass the diagonal/row/column tests, we can then determine this is a valid move
        return True
    
    
    ###############################################################################################################
    if __name__ == "__main__":
        # ask number from user
        print("What sized board would you like?")
        N = int(input('Choose your size: '))
    
        # generate Board that will be used
        Board = [[1 for i in range(0, N)] for j in range(0, N)]
        count = 0
        NQueens(0, Board, N)
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2011-08-09
      • 1970-01-01
      • 2020-06-30
      • 1970-01-01
      • 2021-12-28
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多