我在实线上有M个间隔,每个都有正重量。我需要在它们中选择N,使它们不重叠并给出最大总和。我怎样才能有效地做到这一点?
如果没有N个非重叠区间的子集,则没有解决方案。
如果没有非重叠约束,问题就很简单:选择N个最大权重。由于这个限制,这不再起作用了。在我的情况下,N和M很小(<20),但我希望有一个比穷举尝试所有子集更有效的解决方案。
答案 0 :(得分:4)
您可以使用动态编程解决它。设C(k, i)
为(最多)k
加权区间的最大总和,其中任何一个的左端都不会小于i
。
您可以将i
限制在所有间隔的(实际)起点集合中,k
的范围从0
到N
。
C(k, max(start for start, end in interval))
初始化为0
,将所有其他条目初始化为-infinity。对于权重start
和每个end
的每个时间间隔(w
,k
):
C(start, k) = max(C(start, k), C(next(start), k), w + C(next'(end), k-1))
此处next(x)
返回大于x的最小起点,next'(x)
返回大于或等于x
的最小起点。两者都可以通过二分搜索实现(如果M很小,则可以实现线性扫描)。
总的来说,这将占用O(M * N * logM)时间和O(M * N)空间。
(这假设两端的间隔未闭合,因此(0,100)和(100,200)不重叠 - 如果认为这些重叠,则需要进行小的调整)。
答案 1 :(得分:0)
正在进行中:
受@ PaulHankin解决方案的启发,这是一个重新制定。
通过增加右横坐标对所有间隔进行排序,并迭代地找到直到第K个右边界的最大可能总和。假设您已经解决了前K个区间和所有相关N(从0到K)的所有优化问题。
当您考虑下一个时间间隔时,您可以按如下方式计算新的候选解决方案:对于每N个(直到当前的间隔名义),延长所有先前的解决方案(包括空的解决方案)而不会导致重叠,并保持更好的长度解决方案。
示例:
通过增加N,最佳总和达到第K个右边界
1: 2
2: 2 or 8 => 8 | -
3: 8 or 3 => 8 | 2 + 3 | -
4: 8 or 2 => 8 | 2 + 3 or 8 + 2 => 8 + 2 | 2 + 3 + 2 | -
5: 8 or 9 => 9 | 8 + 2 or 2 + 9 => 2 + 9 | 2 + 3 + 2 | - | -