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