在开放源码的KLSudoku标准数独游戏里,实现了X-Chain和Forcing-Chain的逻辑解法,有朋友询问是如何实现的,特在这里说明一下我的思路。 源码可以从solver.cs里看到。
关于X-Chain和Forcing-Chain解法的说明,可以从数独百科网站查阅:
http://www.sudopedia.org/wiki/X-Chain
A X-Chain is a single-digit solving technique which uses a chain consisting of links that alternate between strong links and weak links, with the starting and ending link being strong. In other words, the chain involves an even number of cells having the target digit as a candidate. The target digit can be eliminated from any cell that is seen by both ends of the X-Chain.
X-Chain解法的链里只涉及到一个候选数,X-Chain是由强链接和弱链接交替连接形成的,强链接意味着在同一个行/列/快里,只有两个数格包含有这个候选数,而弱连接则表示有三个或者三个以上的数格可以包含这个候选数。
对于强连接而言,当前一个几点为真,则下一个节点必然为假,并且如果前一个节点为假,下一个节点就必然为真(这在链的形成中是关键)http://www.sudopedia.org/wiki/Strong_link
对于弱连接而言,只能有一个推断——当前一个节点为真时,下一个节点必然为假。http://www.sudopedia.org/wiki/Weak_link
当强连接和弱连接交替组成的链存在的时候,就可以从第一个节点的真假推断出后面节点的真假。从而就可以对同时与X-Chain里的节点形成连接的一些节点做出推断。
显然,这些可以得到推断的节点也是X-Chain里的一部分,那么如何得到推断呢?
假设我们正在遍历一个X-Chain链,当我们发现下一个节点已经在遍历过程中经历过的时候,就可能可以得到推断了:(弱链首即强链尾,强链首即弱链尾)
如果我们用=>表示强链,->表示弱链,举个例子:
A => B -> C => D -> E => F ->G
对于第一种情况:如果G与A有强连接,则有这样的推断:
而如果G与A无强连接的话,则不能得出上面的推论。因为当A为假,G为假在A与G只是弱连接的时候,是无法得出矛盾推论的。
对于第二种情况:如果H与G是强连接,H与B存在连接,则H是强链尾,B是弱链首,得出B不可能为真,推理过程如下:
这是X-Chain的例子:
这个图就是第一种推断:
这是另外一个X-Chain的例子
说完了X-Chain,再说说Forcing-Chain,Forcing-Chain的说明:http://www.sudopedia.org/wiki/Forcing_Chain
如何利用Forcing-Chain解题呢?
其实和X-Chain是基本一样的,但是Chain里的节点,不再是所有候选数都相同了。
那么不同的候选数如何形成链呢?
答案就是在相同的数格内,不同的候选数之间可以形成链:
下面就是一个例子:
在r9c9的2和6就是一个同数格的弱连接,图里的Chain是这样的:
G2=2 -> I1=2 => I9=2 -> I9=6 => H7=6 -> H2=6 => G2=6 -> G2=2
所以倘若Chain的第一个节点G2=2成立,就会推断出最后一个节点G2=2不成立,形成矛盾,所以G2数格可以排除2!