【问题标题】:Weighted activity selection with partly overlaping times具有部分重叠时间的加权活动选择
【发布时间】:2016-11-25 23:38:29
【问题描述】:

让我们假设我们有 n 个时间表。每个时间表 i 都有一个权重 w(i) 、一个准备时间 prep(i) 和一个休息时间 rest(i) 。

准备时间意味着如果我们选择时间表 i ,我们有义务不选择时间表 i - prep(i) , i - prep(i) + 1 ... i-1 。

休息时间意味着如果我们选择shdule i,我们有义务不选择shedule i+1 ,i+2 ... i+rest(i)

我们的任务是根据上述限制选择合适的时间表,以最大化W。

注意:对于 i=1 ,我们忽略 prep(i) 。我们假设我们已经准备好了。对于 i=n wh 忽略 rest(i)。

限制:一个时间表的准备时间可以与另一个时间表的休息时间重叠。举个例子,如果我们有 rest(5)=2 , prep(8)=2 ,我们可以选择两个时间表。 rest(5)=2 表示如果我们选择 5 ,我们不允许选择 6 和 7 。 Prep(8)=2 表示如果选择 8 ,则不允许选择 6 和 7 。所以我们可以选择 5 和 8。

什么算法最适合这个任务?

如果没有限制,我们可以说每个时间表都有开始时间 i - prep(i) 和结束时间 i + rest (i) 。我们将有一个加权活动选择问题,因此我们可以使用贪心算法获得最优 O(nlogn)。但是限制破坏了我的计划。

【问题讨论】:

    标签: algorithm


    【解决方案1】:

    f(i) 成为最佳答案,这样i-th 活动是最后一项。如果j < prep(i)j + rest(j) < i,我们可以从活动j 转到活动i。换句话说,f(i) = (max of f(j) among all valid j such that j < prep(i) and j + rest(j) < i) + 1。这个公式导致了一个简单的O(N^2) 解决方案。

    但我们可以做得更好!让我们为最大操作保留一个持久的段树(数组中的每个位置一个版本)。最初,它用零填充。对于固定的i,我们使用prep(i) - 1 版本并在[0, i - 1] 范围内执行最大查询。那么f(i) 就是这个最大值加一的值。之后,我们将i + rest(i) 位置的树(即创建一个新版本)更新为f(i)。就是这样。

    我们使用O(N) 获取最大值并将一个元素查询更新为持久段树,因此该解决方案需要O(N log N) 时间和空间,这看起来相当不错。然而,这似乎相当复杂。

    现在让我们摆脱持久性。当我们到达j = i + rest(i) 后,我们可以保持一个“正常”(即非持久段树)并用f(i) 更新位置i 中的值(例如,通过保持一个元素向量在每个位置添加)。我们不再需要关心第二个限制。因此,f(i)[0, prep(i) - 1] 范围内的最大值加一。找到f(i)后,我们推入i + rest(i)位置的待添加向量。

    它仍然使用O(N log N)时间,但空间复杂度现在是线性的,我们不再需要持久的段树(实际上,每次更新只能增加值,我们需要前缀上的最大值,所以我们可以在这里使用二叉索引树而不是段树)。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2020-03-07
      • 1970-01-01
      • 2018-03-03
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-05-26
      • 1970-01-01
      相关资源
      最近更新 更多