【发布时间】:2013-12-29 03:19:30
【问题描述】:
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)
我为 N-queen 问题编写了 Python 代码,它会在找到所有可能的解决方案时打印出来。但是,我想修改此代码,使其返回所有解决方案(板配置)的列表,而不是打印它们。我尝试修改如下代码:
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)
但是,一旦找到第一个解决方案,它就会立即返回,因此solutions 仅包含一个可能的板配置。由于 print vs. return 让我对回溯算法感到困惑,如果有人能告诉我如何修改上述代码,以及将来如何解决类似问题,我将不胜感激。 p>
我认为使用全局变量会起作用,但我从某处了解到,不鼓励使用全局变量来解决此类问题。有人也可以解释一下吗?
编辑:
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
上面返回所有找到的解决方案,而不是打印它们。我还有几个问题(相关部分在上面的代码中标记为Q1和Q2)
- 为什么我们需要
solutions.append(deepcopy(board))?换句话说,当我们执行solutions.append(board)时到底发生了什么?为什么这会导致附加初始板[[0,0,0,0] ...]? - 当
return place_queen(board, row+1, 0)被place_queen(board, row+1, 0)替换时,为什么会遇到问题?我们实际上并没有返回任何东西(或None),但是没有return,列表就会超出索引。
【问题讨论】:
-
你在第一个 sn-p 中在哪里打印它们?
-
print board当当前行超过板子大小时 -
回答您的
global子问题:c2.com/cgi/wiki?GlobalVariablesAreBad -
和
printvs.return:stackoverflow.com/questions/7664779/…(请不要在一篇文章中提出多个问题,尤其是重复的问题)。 -
感谢@jonrsharpe 的链接,但恐怕这不是我要问的。
print和return之间的区别非常明显。让我烦恼的是,当我可以轻松地逐个打印预期结果时,我很难弄清楚如何返回一组预期结果。
标签: python recursion backtracking