舞蹈链Dancing Links

$$Dancing~Links$$

$Dancing~Links$ 可解决的题型有两种:

  1. 精确覆盖问题。
  2. 重复覆盖问题。

精确覆盖问题

给定一个 $n$ 行 $m$ 列的 01 矩阵,问至少选多少行,可以使得每一列恰好有一个 1,求选哪几行满足条件。
适用于稀疏矩阵,即 1 的个数较少。
因为 1 的个数少,在存储的过程中就只存储 1,不存储 0。

暴力:

先考虑暴力,第一种是枚举选择的行再检查,复杂度 $O(n \times m \times 2^n)$。
第二种是把每一行看作一个二进制数,使得给定 $n$ 个 $m$ 位二进制数,选择一些数使得所有的数的或为 $2^m-1$,并且任意两个数做与运算得 $0$ 。复杂度 $O(n \times 2^n)$。

X算法:

  1. 对于现在的矩阵 $M$,选择并标记一列 Q,将 Q 添加至 Ans 中。
  2. 如果所有情况都无解,则该问题无解。
  3. 标记与 Q 相关的行列 $r_i$ 和 $c_i$。
  4. 删除标记的行列,得到新的矩阵。
    • 如果新矩阵为空且 Q 全为 1,算法结束并输出 Ans。
    • 如果新矩阵为空但 Q 不完全为 1,递归求解,跳转至步骤 1。
    • 如果新矩阵不为空,递归求解,跳转至步骤 1。

但 X算法 需要大量的删除恢复操作,所以采取 双向十字链表 进行维护

双向十字链表

双向十字链表存在四个指针域,分别指向上、下、左、右的元素,每个元素 i 对应着一个格子,所以还要表示它所在的行列。
每行有一个行首指示,记为first[];每列有一个列指示,是虚构出来的 $c+1$ 个节点。
每一列要记录该列 1 的个数,记为sz[]

双向十字链表可以支持删除行列、插入行列的操作。

重复覆盖问题

有待更新

posted @ 2022-12-27 15:14  Conan15  阅读(18)  评论(0)    收藏  举报  来源