用舞蹈链来解决数独问题
题目
http://poj.org/problem?id=3074
题意
标准的9×9数独问题,给出一个9×9的矩阵,需要填入1到9之间的数字,使得每一行、每一列以及每一个3×3子矩阵的数字都不重复。题目给出已经填了一部分数字的矩阵,需要将剩余部分填完。
题目解析
可以用舞蹈链的精确覆盖算法来解决数独问题。首先对于每个位置有9个可以填入的数字,共有9×9个位置,所以可以分成9×9×9=729种填充情况,每种情况对应于舞蹈链里十字链表的一行。
对于每一种填充情况,有4个约束:
1. 每个位置都要填数字,不能不填。
2. 一行不能有重复的数字。
3. 一列不能有重复的数字。
4. 每个3×3的子矩阵内不能有重复的数字。
第1种约束可以用十字链表的81(9×9个位置)列来对应,如果舞蹈链计算结果所选择的行能覆盖这81列,则说明81个位置都填了数字。第2种约束也用81列来对应,因为共有9行,要保证每行没有重复的数字,只需要每行都填9个不同的数字就行,如果这81列都被覆盖,且没有重复覆盖,就能满足第二个约束了。第3种和第4种约束与第2种类似,都分别用81列来对应。4种约束一共用4×9×9=324列来对应。
729种填充情况里,每选择一种填充情况,都会占用一个9×9里的一个位置,占用9行里某一行的一个数字、9列里某一列的一个数字,9个3×3的子矩阵里的一个数字,所以每种填充情况都会覆盖4列。因为有一部分位置已经被预先填好了,所以已经填了数字的位置和没填数字的位置,需要分开来处理,没有填数字的位置需要枚举填1~9的9种填充情况,每种填充情况将对应的4列加入十字链表了,已经填了的就直接处理对应数字的填充情况就好了。
代码
1 | /* http://poj.org/problem?id=3074 */ |