什么算法用于查找包含来自多个集合中的每个集合中的至少一个元素的最小集合

时间:2012-07-11 02:39:03

标签: algorithm set graph-algorithm

所以,我有几个集合,我需要找到包含所有集合中至少一个元素的最小数量的集合。为了使这更具体,我有一组服务器名称,每个服务器都有一个服务窗口。给定一个特定的持续时间,我想找到覆盖所有给定服务器的最小服务窗口集。

我已经有代码生成每个所需机器的所有非重叠N分钟时间段的列表。我只是通过生成所有可能的组合来强制它,并选择具有最少数量的独特元素的组合,但这似乎非常低效,即使我首先将设置从所有主机减少到唯一的窗口(特别是更多而不是几个系统。)

然后我想我会按照适合每个时隙的主机数量对时隙进行排序,选择具有最大主机数的插槽,然后重新生成未分配主机的所有插槽列表,选择最受欢迎的广告位,重新计算等,直到占用所有主机。虽然这会给我一个答案,但它并没有真正让我有机会选择最平衡的集合 - 第二个目标是找到一组服务窗口,每个服务的主机数量标准偏差最小窗口。所以,如果我有100个主机,我想优先选择每个窗口给我大约50个主机的窗口,而不是做上述算法可能找到的三个“98,1和1”窗口。但如果我的选项是“98,1,1”或10个窗口,每个10个。我宁愿做这三个。

无论如何,似乎可以使用某种图形来表示这个问题,但是我在CS路径中更多地关注硬件而不是软件,解决图形问题从来都不是我的强项。所以我甚至欣赏一些关于在哪里阅读有关此特定问题或适当搜索条件的更多建议。 :)

2 个答案:

答案 0 :(得分:1)

考虑与每个时间段关联的各个服务器组。您正在构建这些集合的子集,以使其联合包括所有服务器。这被称为Set cover problem,已被证明是NP完全的。这意味着您不能比您在问题中描述的强力方法做得更好,因此请尽可能降低所有主机的唯一窗口数。

<小时/> 附:我不确定为什么templatetypedef删除了他的答案 - 我认为这是正确的。

答案 1 :(得分:1)

这是集合覆盖优化问题,它是NP难的。这意味着你不能比最坏情况中的暴力做得更好。也就是说,你可以快速找到一些套装。但你绝对可以简化问题 - 特别是现实世界的数据。

我首先要对数据进行多次转换。想象你的套装是一个布尔网格。每列代表一个服务器,每行代表一个集合。单元格中的True表示服务器存在于该集合中。

  1. 您可能有多个服务器属于完全相同的集合。也就是说,该矩阵中可能会有相同的列。您可以删除任何重复的列。因此,如果A和B具有完全保存服务窗口,获取包含A的覆盖也将包括B.您可以通过使用此列中的值对每个服务器进行散列,然后检查同一散列桶中的每个服务器来快速执行此操作相同的会员资格。只保留一台服务器,并创建一个“骑行”服务器列表。例如。从现在开始,这些服务器将被视为您的集合的单个成员。

  2. 删除任何作为单个其他集的子集的集合。例如如果你有{1,2,3}和{1,2}。从问题中删除{1,2}。为你的封面选择套装{1,2,3}永远是一个更好的选择。所以转储子集 - 例如删除所有这些行。

  3. 迭代每个服务器(例如每列)。每个服务器只存在于一个集合中(例如,列中为true),然后设置必须成为解决方案的一部分。因此,将该集添加到解决方案中,并将其从矩阵中删除。现在,您可以从矩阵中删除已删除的集合中的任何列。假设服务器A仅存在于集合1中,即{A,B,C}。设置良好1 必须成为解决方案的一部分。如果是,那么我自动知道将自动覆盖服务器A,B,C。所以我从矩阵和A,B,C的列中删除了集合。

  4. 删除每组中的所有服务器。他们将处于任何解决方案中。

  5. 在此之后,除非您的数据集“反常”,否则您的实际问题集应该大大减少。真实世界的数据可能会有序,以至于一堆行和列都不会出现问题。

    我确信有很好的方法可以找到一个答案,在实践中会给你一个非常接近最佳覆盖的地方,而不是比现实世界数据更强大的时间。

    我会考虑使用DP或A-Star搜索解决方案。我没时间了。我可以稍后草拟它。