给定时间间隔列表,我需要找到最大不重叠间隔的集合。
例如,
如果我们有以下间隔:
[0600, 0830], [0800, 0900], [0900, 1100], [0900, 1130], [1030, 1400], [1230, 1400]
同时也考虑到时间必须在范围之内[0000, 2400]。
[0000, 2400]
最大的非重叠间隔集为[0600, 0830], [0900, 1130], [1230, 1400]。
[0600, 0830], [0900, 1130], [1230, 1400]
我了解最大包装数量是NP-Complete。我想确认我的问题(间隔仅包含开始和结束时间)是否也是NP-Complete。
如果是这样,是否有办法在指数时间内找到最佳解决方案,但具有更智能的预处理和修剪数据。或者如果有一个比较容易实现的固定参数易处理算法。我不想去一个近似算法。
这不是NP完全问题。我可以想到一种O(n * log(n))使用动态编程来解决此问题的算法。
O(n * log(n))
假设我们有n个间隔。假设给定范围是S(在您的情况下为S = [0000, 2400])。假设所有间隔都在内S,或者消除所有不S在线性时间内的间隔。
S
S = [0000, 2400]
预处理:
A[n]
Next[n]
n
i,
Next[i]
DP:
假设范围内的最大不重叠间隔[A[i].begin, S.end]为f[i]。这f[0]就是我们想要的答案。
[A[i].begin, S.end]
f[i]
f[0]
f[n] = 0
f[i] = max{f[i+1], 1 + f[Next[i]]}
上面的解决方案是我乍看之下提出的解决方案。在那之后,我还想出了一种更简单的贪婪方法(但是从大的O表示法来看不是更快):
(具有与上述DP方法相同的符号和假设)
前处理:排序的所有间隔由他们 结束 点。假设我们得到一个B[n]n个间隔的数组。
B[n]
贪婪:
int ans = 0, cursor = S.begin;
for(int i = 0; i < n; i){ if(B[i].begin >= cursor){ ans; cursor = B[i].end; } }
以上两种解决方案是我想到的,但是您的问题也称为 活动选择问题 ,可以在Wikipedia http://en.wikipedia.org/wiki/Activity_selection_problem上找到。
同样, 算法导论 在16.1中深入讨论了这个问题。