查找Set-cover问题的最小尺寸集覆盖的算法

时间:2010-11-26 01:41:24

标签: algorithm programming-languages

在Set Covering问题中,我们给出了一个宇宙U,例如| U | = n,并且设置S1,......,Sk是U的子集。集合覆盖是来自某些集合的集合C. S1,......,Sk,其联盟是整个宇宙U.

我正在尝试提出一种算法,该算法将找到最小数量的集合覆盖,以便我可以证明集合覆盖的贪婪算法有时会找到更多集合。

以下是我的想法:

重复每一组。 1.封面< -Seti(i = 1 ,,, n) 2.如果一个集合不是任何其他集合的子集,那么请将该集合置于封面。

但它在某些情况下无效。 请帮我弄清楚找到最小集合覆盖率的算法。

我仍有问题在网上找到这个算法。有人有什么建议吗?

2 个答案:

答案 0 :(得分:7)

设置封面是NP难的,所以不太可能比查看所有可能的组合组合更有效,并检查每个组合是否是封面。

基本上,看看1套,然后2套等的所有组合,直到它们形成封面。

修改

这是一个伪代码示例。请注意,我并不认为这是有效的。我只是声称没有更高效的算法(算法会比多项式时间更糟,除非发现真的很酷)

for size in 1..|S|:
    for C in combination(S, size):
          if (union(C) == U) return C

其中combination(K, n)返回所有可能的大小n,其元素来自K

修改

但是,我不太清楚为什么你需要一个算法来找到最小值。在问题中,您声明要表明集合覆盖的贪婪算法有时会发现更多集合。但这很容易通过一个反例来实现(并且在维基百科条目集中显示了一个反例)。所以我很困惑。

修改

combination(K, n)的可能实现是:

if n == 0: return [{}] //a list containing an empty set
r = []
for k in K:
    K = K \ {k} // remove k from K.
    for s in combination(K, n-1):
        r.append(union({k}, s))
return r

但结合封面问题,人们可能希望从基础案例n == 0执行覆盖测试。好。

答案 1 :(得分:0)

请使用稀疏矩阵尝试使用Donald E. Knuth算法-X进行精确的覆盖。必须稍加调整,以解决最小化布套问题。