DLX (Dancing Links X)
###概念
精确覆盖问题 Exact Cover Problem
在一个全集 $X$ 中若干子集的集合为 $S$ ,精确覆盖是指,$S$ 的子集 $S$ ,满足 $X$ 中的每一个元素在 $S$ 中恰好出现一次。在计算机科学中,精确覆盖问题指找出这样的一种覆盖,或证明其不存在。
算法X Algorithm X
可用于解决精确覆盖问题的一种算法,我们每次选择一个没有被覆盖的元素,然后选择一个包含它的集合进行覆盖。不断回溯,知道所有元素被覆盖。
这里我们可以把每个元素当做一列,每个集合当做一行,也就是每次在矩阵中选择一个没有被删除的列,然后枚举删除该列为一的哪一行,不断回溯,直到矩阵变成一个全零矩阵。
但是如果暴力回溯的话时间复杂度不够优秀,所以可以使用 Dancing Links 优化,所谓 Dancing Links 就是一个循环十字链表,那么这种用 Dancing Links 优化的算法 X 就简称为 $DLX$。
###实现
1 | class DLX |
应用:解决数独问题
我们有了 DLX 算法之后,就可以将数独问题转化为精确覆盖问题然后快速解决了,事实上, DLX 在解决数独问题上的表现十分出色。
虽然标准数独是 $9\times9$ 的,但是对计算机来说范围太小了,所有我们以 $16\times16$ 的数独为例:
列代表这需要满足的条件,分析一下数独的游戏规则有如下四种条件:
- SLOT a b : 第 $a$ 行第 $b$ 列要有字母;
- ROW a b : 第 $a$ 行要有字母 $b$ ;
- COL a b : 第 $a$ 列要有字母 $b$ ;
- SUB a b : 第 $a$ 个子方阵要有字母 $b$ ;
共有 $16\times16\times4=1024$ 列
行代表着待选的集合,需要注意的是,这里的集合中只有一个元素(这里的元素也就是需要满足的条件),表示的是对于一个格子的状态,也就是某一个格子填什么。
共有 $16\times16\times16=4096$ 行
由于每行满足四个条件,故每行有 $4$ 个 $1$ ,加起来就是 $4096\times4=16384$ 个节点,用十字链表储存占有空间很小。
1 |
|