在Set Covering问题中,我们给出了一个宇宙U,例如| U | = n,并且设置S1,......,Sk是U的子集。集合覆盖是来自某些集合的集合C. S1,......,Sk,其联盟是整个宇宙U.
我正在尝试提出一种算法,该算法将找到最小数量的集合覆盖,以便我可以证明集合覆盖的贪婪算法有时会找到更多集合。
以下是我的想法:
重复每一组。 1.封面< -Seti(i = 1 ,,, n) 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进行精确的覆盖。必须稍加调整,以解决最小化布套问题。