python的回溯和递归_python 想了解递归/回溯,简单的数独示例 - 糯米PHP

[此帖子收录不佳,因此我进行了一些建议的修改,以期使其后代得到改善。我希望它对以后发现它的人有所帮助!]

我一直在尝试使用一个简单的Sudoku示例来理解递归/回溯/ DFS。我对Sudoku示例本身并不真正感兴趣,因此,根据建议,我将下面的示例最小化为2x2数独板,以便仅关注使我困惑于递归的问题(感谢@MisterMiyagi的建议)。

在下面的代码中,我有一个辅助函数check_board,该函数采用2x2矩阵并检查其行和列中是否有任何数字重复(即,检查输入的2x2数独是否有效)。然后,该函数solve_sudoku被我理解为解决数独问题的标准DFS /回溯算法,方法是选择第一个空位置(用0表示),然后在其中尝试值1和2,然后递归寻找解决方案。

所以输入[[0,0], [0,2]]应该是输出[[[2,1],[1,2]],但是我正在接收输出False。

@ThierryLathuille helped by noticing the problem in the code: after trying each possible descendant node (in this case, by trying both values 1, 2), I missed the "backtracking" step, and need to add a line resetting the value to 0, meaning that square in the matrix would be stuck in a 2 for all subsequent calls (or, in the original 9x9 example, stuck at a 9):

When you see that the last value you tried in a square can't lead to a valid solution, you try the next one, until you reach 9. At this point, you return and go back to incrementing the value in the previous square, but you current one still contains the value 9, so it is considered as non available for the next attempts.

You just have to put it back to its original value of 0 before returning:

Now here's where I'm still confused and the point of the question: I am trying to think about the recursion like a tree. Once one of the nodes has tried every value for a square and its descendant nodes have all come back False, doesn't it just report False back up to its parent? Why would anyone else look at that board with the 2 again?

If you can help with my understanding of recursion, I'd really appreciate it!

Edit: @ThierryLathuille answered the question again in a comment! Thanks so much!

Note that when calling your function recursively, you don't pass copies of the board, but only manipulate the same board everywhere. As your code worked, each time you explored a branch of the tree, all the squares you touched during the exploration were left with a non-zero value, so they were not considered as free any more.

I had the mistaken idea that whenever a function is called in recursion, it gets a new copy of all its variables to act on. Which of course it does, but not of the input! Another fix to the code would be to use Python's copy module with the line copy_board = copy.deepcopy(board) and operate on and return copy_board at each instantiation of the function, which is what I mistakenly thought Python always did in recursion.

也许这与按值传递与按引用传递有关,而Python总是按引用传递?对此主题的任何其他讨论仍将不胜感激!

这是用行将其注释掉的破断代码:

def check_board(board: list):

for i in chars:

for j in chars:

for k in chars:

if k == j:

continue

if board[i][j] == board[i][k] and board[i][j] != 0:

return False

if board[j][i] == board[k][i] and board[j][i] != 0:

return False

return True

def solve_sudoku(board: list):

chars = range(2)

if not check_board(board):

return False

for i in chars:

for j in chars:

if board[i][j] == 0:

for a in chars:

board[i][j] = a+1

if solve_sudoku(board):

return solve_sudoku(board)

# uncommenting this next line fixes the algorithm

#board[i][j] = 0

return False

return board

board = [[0,0],[0,2]]

if __name__ == "__main__":

print(solve_sudoku(board))

输出:False

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值