第 73 讲:计算机算法
今天我们来介绍一些基本的计算机编程算法。它对于计算机的解题来说也是相当重要,但由于它的算法也显得很暴力,所以这一类算法也被数独界称为Brute Force。我们来看一下。
不过教程为了面向广大读者,我们不会详细给出每一种思路的算法的源代码。
Part 1 特雷伯尔表
这一种方法名字比较多,考虑到直译“强制网”会和网技巧名称产生冲突,所以没有使用这个翻译模式,它的英文名有Forcing Net、Trebor's Tables和Tabling三种,都是等价的意思,而在编程里,它更靠近表格存储的运算,所以这里我们采用的是表格的名称的直译,即特雷伯尔表。你可以把这个技巧被理解为动态强制链组,即在强制链组内包含动态分支的现象,甚至在分支上还带有分支的情况。
这一类的算法通常复杂度都相当大。如图所示。

这样的算法包含两种计算思维:矛盾型(Contradiction)和验证型(Verity)。由于显得比较暴力,所以这一点这里提一下即可。
此时请参考如下的在GitHub上的Hodoku代码的仓库:
https://github.com/Sunnie-Shine/Hodoku,
并找到上述两个文件即可。
Part 2 回溯
回溯是一种比较死板的思维。它尝试为r1c1的第一个候选数(r1c1(1))假设为真,然后尝试以这个填法来尝试r1c1所在的行列宫是否存在重复。如果重复了,就说明了数字填错了,我们就可以反推出r1c1(1)是错误的;然后我们再次尝试r1c1 = 2,然后依然看r1c1的所在行列宫里是否存在重复。如果不重复的话,我们就继续假设r1c2的填数(从1开始)。
以这样的形式,直至得到整个盘面,所以这个算法是显得很暴力的,但它作为数独的基本算法之一,需要编程学习的朋友们记住和灵活使用,我们将代码列到了本教程的附录之中。
Part 3 舞蹈链
舞蹈链(Dancing Links for Sudoku,简称DLX,取Dancing的D、Links的L和[ks]组合的发音X),是一种算法,同时也可以看作是一种数据结构,因为它在计算过程之中,使用到的是一种特殊的链表结构——双向循环十字链表(Bidirectional Orthogonal Linked List)。它为普通链表的使用增加了更加有趣的使用:双向和十字。它不仅仅可以完美解决数独的“行列宫不重复”的情况,还能解决类似于这样的其他类型的谜题,例如八皇后问题(Eight-queen Puzzle)等。不过八皇后问题依然可以通过回溯得到解。不过,这个算法的实现原理比较复杂,和之前的Forcing Net一样,我们将不在此作出探讨,不过我们会在附录里列出舞蹈链解决数独问题的算法代码(C#语言版本,熟悉Java的可以类比,并给出Java和C#不同的地方,方便你进行转换)。
Part 4 Linq算法
在C#语言里,我们拥有一种特殊的语法和函数库:Linq。Linq是Language Integrated Query,即语言集成查询的缩写,取了L、in、q三部分凑起来的,读作/lɪŋk/(读音类似于单词link)。
从名字上可以看出,它实际上在编程语言的层面上实现了SQL那一套的查询操作,不过是轻量级的;而本质上,Linq提供的是可使用foreach循环的IEnumerable<T>和IEnumerable对象的一些扩展方法,用于遍历集合,以完成类似于SQL的增、删、改、查的操作。因此在C#里,我们将使用Linq函数库来操作程序变量的行为为Linq to Objects,即应用于对象的Linq。
数独里,我们可以使用Linq算法,即采用Linq的查询修改功能来为一个盘面的信息进行修改和查询。它的大体思路是,逐个查询盘面表示的信息为空的单元格,并尝试使用单元格的所有候选数挨个替换它,然后迭代执行的一种思维方式。
至此,整个教程就全部结束了。后面的附录给出了教程的一些附带内容。