在集合覆盖问题中,给我们一个宇宙U,使得| U | = n,并且集合S1,…,Sk是U的子集。集合覆盖是S1,…中某些集合的集合C。 …,Sk的联合是整个宇宙U。
我试图提出一种算法,该算法将找到最少的集合覆盖数,以便可以证明集合覆盖的贪婪算法有时会发现更多集合。
以下是我的想法:
为每组重复。1. Cover <-Seti(i = 1 ,,, n)2.如果一个集合不是任何其他集合的子集,则将该集合当作盖子。
但在某些情况下不起作用。请帮助我找出找到最小覆盖范围的算法。
我仍然无法在网上找到此算法。有人有什么建议吗?
集合覆盖是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)
n
K
但是,我不太确定为什么您需要一种算法来找到最小值。在该问题中,您指出要证明集合覆盖的贪婪算法有时会找到更多集合。但这可以通过反例轻松实现(并且反例在Wikipedia条目中显示为封面)。所以我很困惑。
一个可能的实现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。好。
n == 0