精确覆盖问题、Algorithm X 与 Dancing Links(DLX)

精确覆盖(Exact Cover)问题

精确覆盖

S 为集合 X 的若干个子集构成的集合,若存在 S 的一个子集 S*,满足 X 中的元素有且只有一次包含在 S* 的一个元素中,那么称 S* 为 X 的一个精确覆盖。

S*属性

根据定义 S* 具有以下属性:
1. S* 中任意两个元素交集为空。
2. S* 中所有元素并集为 X。

例子

假定 S = { A, B, C, D} ,X = {1, 2, 3, 4, 5, 6} ,其中:
A = {1, 3, 5}
B = {2, 4}
C = {2, 3, 4, 5, 6}
D = {2, 4, 6}
那么 S* = {A, D} 是 X 的一个精确覆盖。而 {A, B}、{A, C}
分别不满足上述属性2、1,因而不是 X 的一个精确覆盖。

精确覆盖问题

精确覆盖问题是指给定一个 S,确定是否存在对 X 的一个精确覆盖,这是一个 NP 难问题。
这个问题可以用一个矩阵来表示
矩阵表示
在矩阵表示情形下,精确覆盖问题可以表述为选择特定的行使得所有的列有且只含有一个1。
精确覆盖

Algorithm X

X
不要被名字吓到,Donald E. Knuth 这么叫它的,本质上还是一个回溯法。其步骤如下所示:
维护两个集合——当前尚未满足的限制条件和可供选择的选项。
1.检查当前未满足的限制条件集合,若为空,则表示问题已经解决,输出答案并返回
2.否则选择其中一个不满足的限制条件。(可以使用启发式算法尽量加快代码运行)
3.找满足限制条件的选项集合,若为空,则表示当前这个位置不可能产出正确答案,返回。(剪枝)
4.否则,遍历上述选项集合(这一步可以是随机选择,这样会导致一个 non-deterministic 算法):
(1)当前选项可能满足多个限制条件,故对每个满足的限制条件,将其从未满足限制条件集合中移除,并且将所有能满足这个限制条件的选项也移除(因为精确覆盖要求不可重叠,若考虑完全覆盖则此时不需要移除)
(2)上述操作完成后形成“尚未满足的限制条件”和“可供选择的选项”这两个集合的子集合——即子问题,对此子问题递归求解。
(3)复原:上述递归完成后,在测试下一个选项前,我们需要恢复原来两个集合的样子。所以要将之前移除的条件和选项全部恢复。
使用 X 算法对上述例子求解如下:
X算法求解

可以看出上述操作需要一对对偶操作——将一个元素从矩阵中移除,一番操作完成后还要将移除的这个元素重新添加回矩阵中去,这个用普通结构实现可能会比较复杂。

Insight——双向链表操作

将双向链表中的一个元素拿掉

x.left.right=x.right
x.right.left=x.left

双向链表删除
将该元素重新加入链表

x.left.right=x
x.right.left=x

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值