我一直在研究数独求解器,我目前的求解器使用回溯算法,但仍然需要很长时间。
在大多数情况下,我希望将其降低到不到一秒。因此,我决定用跳舞链接算法重写它,理解它是更好的蛮力方法之一,尤其适用于数独难题等约束问题。
我试图阅读 Wiki 和Knuth 的论文,但是它们都很难理解并且非常冗长。
我还阅读了 Suododia 的版本,似乎一旦进入数独的实现,它就变得太抽象了。
有人可以尝试解释 Dancing Links 算法,而不是根据它的推导而是它的实现吗?(以数独为例会很棒)
谢谢!
您可能对我在 javascript 中的实现感兴趣。
首先,您必须了解 Exact Cover。精确覆盖问题是一个问题,你有一堆选择,一组约束,你的挑战是选择一堆选项,这些选项将恰好满足每个约束一次。
例如,考虑某人创建他们的冰舞程序的情况。他们有许多技巧需要向评委展示,并且不想多次表演任何技巧。他们有许多序列,这些序列是可以组合在一起的技巧组,他们希望选择理想的序列选择来覆盖所有技巧。在这个例子中,约束是他们必须执行每一个技巧。选择是他们可以纳入日常活动的可能序列。
表示此类问题的一个好方法是绘制一个表格,其中约束是列,选择是行,并且在特定选择满足该约束的单元格中有一个大 X。
事实证明,给定正确的约束和选择,数独可以描述为精确覆盖问题。
好吧,假设你已经明白了,现在你需要了解算法 X。Knuth 说:“算法 X 只是对明显的试错方法的陈述。(事实上,我想不出任何其他合理的方法)一般来说,完成这项工作的方法。)”。所以这是我对算法 X 的描述:
既然你明白了,你就可以理解跳舞的链接了。Dancing Links 是一种有效实现该算法的方法。跳舞链接的关键在于,在链表中,当您删除一个节点时(可以通过修改其邻居的指针来有效地完成),您删除的节点具有您需要将其添加回来的所有信息到链表(如果你猜到它是解决方案的一部分时你错了)。再加上如果你把所有的链表都做成循环的,那么你会突然失去很多特殊情况,这几乎就是所有的跳舞链接。
虽然这个问题很老,但我想我会补充:
这个页面使算法很容易理解:Zendoku writeup。直到我在那个链接上读到它,我一直认为这一定是一个超级高级的算法,但真的一旦你可以想象它,它只是一个非常巧妙但简单的解决方案。
此外,我在 C# 中的实现应该相当容易阅读......我确信将有助于将各种类拆分为不同的文件。
它主要是 Knuth 的 pdf 的直接实现,但有一些面向对象的优化(实际上,自从几个月前我这样做以来,我不太记得我偏离了 pdf 多少)