Python 为什么我的回溯算法不起作用,并产生重复条目的方块?

Python 为什么我的回溯算法不起作用,并产生重复条目的方块?,python,python-3.x,algorithm,recursion,backtracking,Python,Python 3.x,Algorithm,Recursion,Backtracking,嗨,我正在尝试使用回溯来解决一个问题 我编写了一个函数来返回一个空值(如果存在),这里0表示一个空值。另一个测试将数字放置在棋盘中特定位置是否有效(基于数独规则)的函数,以及另一个实现回溯以实际解决谜题的函数 当我运行算法时,提供了电路板,我得到: [[2, 1, 3, 7, 4, 5, 6, 8, 9], [1, 3, 4, 2, 5, 6, 8, 9, 7], [5, 6, 9, 4, 3, 8, 2, 7, 1], [7, 5, 8, 1, 2, 4, 9, 3, 6], [4,

嗨,我正在尝试使用回溯来解决一个问题

我编写了一个函数来返回一个空值(如果存在),这里0表示一个空值。另一个测试将数字放置在棋盘中特定位置是否有效(基于数独规则)的函数,以及另一个实现回溯以实际解决谜题的函数

当我运行算法时,提供了电路板,我得到:

[[2, 1, 3, 7, 4, 5, 6, 8, 9],
 [1, 3, 4, 2, 5, 6, 8, 9, 7],
 [5, 6, 9, 4, 3, 8, 2, 7, 1],
 [7, 5, 8, 1, 2, 4, 9, 3, 6],
 [4, 8, 7, 5, 6, 9, 1, 2, 3],
 [3, 2, 5, 6, 9, 7, 4, 1, 8],
 [9, 7, 6, 3, 8, 1, 5, 4, 2],
 [6, 9, 2, 8, 1, 3, 7, 5, 4],
 [8, 4, 1, 9, 7, 2, 3, 6, 5]]
它似乎是在逐列逐行的基础上工作的。但是
3x3
方块不正确

例如,以左上角的正方形为例

[[2, 1, 3],
 [1, 3, 4],
 [5, 6, 9]]
这包含重复的条目,例如
3
,并且每个编号
1-9
也不包含一次

根据我的
可行性移动
方法,这是不允许的

很明显,我犯了一个错误,但我不知道在哪里


有什么想法吗

原因是
可行性移动的这一部分有错误:

row = coordinate[0] // 3
col = coordinate[1] // 3

for i in range(x * 3, x * 3 + 3):
    for j in range(y * 3, y * 3 + 3):
        if board[row][col] == number and (i, j) != coordinate:
            return False
迭代应基于
,而不是基于
x
y
。当您从
board
读取值时,应使用
i
j
作为索引。现在,你看了9次板上的同一个单元格

row = (x // 3) * 3
col = (y // 3) * 3

for i in range(row, row + 3):
    for j in range(col, col + 3):
        if board[i][j] == number and (i, j) != coordinate:
            return False
但是,您的算法太慢,无法在合理的时间内解决此难题。您应该通过以下几点改进算法:

  • 不要实时查找空白单元格。相反,将它们收集到队列中,然后从队列中弹出(回溯时将它们放回原处)
  • 不要检查某个值是否对某个单元格有效,而是保持领先一步,跟踪每个单元格中哪些值仍然有效(在
    集合中)。在算法一开始就初始化它
  • 放置值时,更新受影响的单元格集
最后两点似乎没有什么好处,因为它只是将扫描行、列和框的工作转移到算法中的另一个时刻,但好处在于:

  • 为了使递归树保持狭窄,请优先考虑具有尽可能少的值的单元格,理想情况下只有一个值。为此,可以使用python的
    heapq
    ,它应该应用于我在第一点中提到的队列

我把实现留给你,因为这不是你的问题。不管怎样,网上有很多实用的例子。

这是一个很好的答案,谢谢。关于这些技术的改进,我以前从未听说过。你能提供一个开始学习的地方吗?你推荐吗?我建议你只编写很多程序,也许在提供代码挑战的网站上。选择一个你自己解决后可以看到其他解决方案的地方;并向他们学习。对于数独,我并没有真正找到我所描述的,但看起来是一个很好的方法。
row = (x // 3) * 3
col = (y // 3) * 3

for i in range(row, row + 3):
    for j in range(col, col + 3):
        if board[i][j] == number and (i, j) != coordinate:
            return False