集封面问题的扩展版

Posted

技术标签:

【中文标题】集封面问题的扩展版【英文标题】:Extended version of the set cover problem 【发布时间】:2021-08-29 04:56:48 【问题描述】:

我一般不会就 SO 提出问题,所以如果这个问题似乎不适合 SO,请告诉我(当然,我们仍会感谢您的帮助)。

我还是一名学生,目前正在学习算法课程。我们最近了解了分支定界范式,由于我没有完全理解它,所以我尝试在我们的课本中做一些练习。我遇到了一个特殊的 Set Cover 问题实例:

令 U 是一组元素,S = S1, S2, ..., Sn 是 U 的一组子集,其中所有集合 Si 的并集等于 U。概述分支定界算法求 S 的最小子集 Q,使得对于 U 中的所有元素 u,Q 中至少有两个集合,其中包含 u。具体来说,详细说明如何将问题分解为子问题以及如何计算上下界。

我的第一个想法是按降序对 S 中的所有集合 Si 进行排序,根据它们包含的元素的数量尚未被当前选择的 S 的子集覆盖至少两次,因此我们当前的 Q 实例。然后我正在考虑递归地解决这个问题,我按排序顺序选择第一个集合 Si 并进行一个递归调用,我在其中使用这个集合 Si 和一个我没有的地方(意味着从那些递归调用开始,子集是 no考虑时间更长)。如果我选择它,我将遍历这个选定子集 Si 中的每个元素并为其所有元素增加一个计数器(在递归调用之前),这样我最终会知道,当一个元素已经被两个或更多选择的元素覆盖时子集。由于我为每个递归调用对未选择的集合 Si 进行了排序,因此理论上(至少在我看来)我总是会做出目前最好的选择。而且由于我基本上创建了递归调用的二叉树,因为我总是使用当前选择的最佳子集进行一次调用,而在我没有选择的情况下,我最终会涵盖所有 2^n 种可能性,这意味着最终我会找到最佳的解决方案。

我现在的问题是我不知道或者更确切地说我将如何实现上限和下限的启发式,所以算法可以丢弃二叉树中的一些路径,这永远不会比当前最好的路径更好问:如果能得到任何帮助,我将不胜感激。

【问题讨论】:

一个通用的答案是使用线性规划来获得下限,并使用贪心算法来获得上限。实际上,我通常甚至不会费心评估独立的上限,而是支持使用最佳优先回溯的深度优先搜索。 【参考方案1】:

这是一个简单的下界启发式算法:找到包含最多未被两次覆盖的元素的集合。 (如果有多个集合具有相同的最大可能数量的这些元素,则选择哪个集合并不重要。)假设总共有 u 个这些元素,并且这个集合包含 k

这个下限也适用于常规集合覆盖问题。与分支定界一样,使用它可能会也可能不会在给定实例上带来更好的整体性能,而不是简单地使用总是返回 0 的“启发式”。

【讨论】:

【参考方案2】:

首先,一些建议:不要在每次递归/循环时重新排序S。排序是一项昂贵的操作 (O(N log N)),因此将其置于循环或递归中的成本通常比您从中获得的收益要高。通常,您希望在开始时排序一次,然后在整个算法中利用该排序。

您选择的排序,按 S 子集的长度递减是一个很好的“贪婪”排序,所以我会说只是先做,然后不要重新排序。您不会跳过递归中不理想的子集,但检查冗余/非理想子集仍然比每次重新排序要快。

现在您可以使用什么上限/下限?一般来说,您希望您的边界和边界检查尽可能简单和高效,因为您将要检查它们很多

考虑到这一点,上限很容易:使用您迄今为止找到的最短集合长度解决方案。最初将您的上限设置为var bestQlength = int.MaxVal,某个最大值大于n,即S 中的子集数。然后在每次递归时检查currentQ.length > bestQlength,如果是,则此分支超过上限-界限,你“修剪”它。显然,当您找到新的解决方案时,您还需要检查它是否比您当前的bestQ 更好(更短),如果是,那么同时更新bestQbestQlength

一个好的下限有点棘手,对于这个问题,我能想到的最简单的方法是:在将新子集 Si 添加到 currentQ 之前,检查 Si 是否有 两次或更多次不在currentQ 中的元素,如果没有,则此Si 无法以任何方式对您尝试构建的currentQ 解决方案做出贡献,因此请跳过它并转到 S 中的下一个子集。

【讨论】:

以上是关于集封面问题的扩展版的主要内容,如果未能解决你的问题,请参考以下文章

请问各位:wii 硬盘版怎样显示封面?

速领!一大批限定版微信红包封面来袭,先到先得

xbox360怎么更新游戏封面

微信红包封面哆啦A梦 x GUCCI古驰限定版!!

劲爆!微信官宣 100w 个虎年限量版红包封面,超好看!速度撸!!

xbox360 如何导入游戏封面