【问题标题】:Brute-force sudoku solver: backtracking?蛮力数独求解器:回溯?
【发布时间】:2010-07-23 17:01:23
【问题描述】:

如果发现在其中放置任何数字 1-9 的单元格将是非法移动,则解决数独难题的 a brute-force algorithm 实现将失败。

实现是用 C 语言编写的,电路板由 9x9 数组表示。求解器从 9 开始倒计时,直到达到一个合法数字,如果没有达到,它会输出一个 0。

零也表示要填充的单元格。如果输入一串零(空板),则输出(截断):

9 8 7 6 5 4 3 2 1
6 5 4 9 8 7 0 0 0

最后三个零之所以存在,是因为之前填写的值没有改变。 How我可以阻止求解器这样失败吗?

【问题讨论】:

  • 也许你在实现中有错误
  • 我觉得像 Peter Norvig (norvig.com/sudoku.html) 这样的简单约束求解器的存在使蛮力求解器变得过时且无趣。

标签: c algorithm brute-force sudoku


【解决方案1】:

如果您当前要在某个位置输入零,请返回上一个您输入数字的位置并继续倒计时,直到找到该位置的另一个数值。

例如,在您的示例中:

9 8 7 6 5 4 3 2 1
6 5 4 9 8 7 0 0 0

不要将零放在三下面,而是返回并尝试将六放在四下面。

【讨论】:

  • OP:是的,回溯是你想要的,这就是你实现它的方式。
  • 好吧,如果我这样做,7 变为 3,后面的 0 仍然存在,但最后的 0 变为 7。程序只是修改最后更改的单元格。
  • 是之前细胞的错吗?
  • 当您返回上一个单元格时,您需要在此之后从该单元格开始填充 - 如果您回溯,则必须从您回溯到的地方再次开始工作。
  • 我怎么知道回溯到哪里?除了更改以前的单元格并查看已归零的单元格是否可以开始更改之外的任何其他内容?
【解决方案2】:

不要把每一个“移动”都当作正确的移动。例如。放置最后 7 个 似乎 没问题,但这样做是为了在 next 单元格中没有留下有效的移动。因此,一旦遇到“无法移动”的情况,请返回并尝试下一个选项。迭代,你就会有你的解决方案。

当然,更好的方法是对只剩下少量选项的地方进行暴力破解;遍历所有单元格并开始暴力破解剩余选项数量最少的单元格。当从全零开始时,你最终会得到

9 8 7 6 5 4 3 2 1
6 5 4 0 0 0 0 0 0
3 2 1 0 0 0 0 0 0

这是合法的,无需回溯一次。

【讨论】:

    【解决方案3】:

    您可以通过将您的猜测压入堆栈来做到这一点。每次您最终想要输出零时,请将您的最后一个答案从板上弹出并继续计数。

    因此,如果您在 (2,3) 中猜到 3,然后您正在查看 (3,3) 并达到零,请返回 (2,3) 并尝试 2,然后尝试 1,然后弹出到之前你的 (2,3) 猜测等等。

    【讨论】:

    • 那么,保留堆栈中的每个工作单元格值、每个工作猜测值,还是用堆栈替换我的多维数组(表示单元格)?
    • 最简单的方法可能是将猜测保留在堆栈中。您需要保留二维数组,以便轻松了解当前单元格的合法值是什么。
    猜你喜欢
    • 2013-04-05
    • 1970-01-01
    • 2023-03-27
    • 1970-01-01
    • 2011-05-01
    • 2017-12-16
    • 1970-01-01
    • 2021-12-11
    • 2014-02-07
    相关资源
    最近更新 更多