Эта точная проблема рассматривается алгоритмистом .
Алгоритм алгоритма в стиле строчной линии решит вашу проблему оптимально.
Предполагая, что выЕсли вы хотите сначала охватить как можно больше непересекающихся областей, а затем использовать наименьшее число разделов с учетом первого ограничения, тогда этот алгоритм решит проблему за O (n ^ 2) раз.
Основная идея состоит в том, чтобы идти по порядку сверху вниз и брать раздел только тогда, когда вы «обнажены», то есть не охватывали данный раздел.Когда вы вынуждены занять раздел, выберите тот, который больше всего вас охватит, в «будущее».Эта реализация O (n ^ 2), но вы можете сделать это O (n log (n)), немного улучшив управление Cands.
#!/usr/bin/python
START_EVENT, END_EVENT = 0, 1 # handle starts before ends at same point
def max_future(cands):
return max(cands, key=lambda c: (c[1], c)[1])
def cover_max_segment_min(intervals):
events = []
for interval in intervals:
events.append((interval[0], START_EVENT, interval))
events.append((interval[1], END_EVENT, interval))
cands = []
outputs = []
alive = None
# Handle events by
# event time,
# starts before ends,
# longer endings before shorter endings
events.sort(key=lambda x: (x[0], x[1], -x[2][1]))
for k, event_type, interval in events:
if event_type == START_EVENT:
cands.append(interval)
if event_type == END_EVENT:
cands.remove(interval)
if interval is alive:
alive = None
if not alive and cands:
outputs.append(max_future(cands))
alive = outputs[-1]
return outputs
assert cover_max_segment_min([(0, 3), (1, 4), (3, 5)]) == \
[(0, 3), (3, 5)]
assert cover_max_segment_min([(0, 3), (3, 5), (1, 4)]) == \
[(0, 3), (3, 5)]
assert cover_max_segment_min([(0, 3)]) == [(0, 3)]
assert cover_max_segment_min([]) == []
assert cover_max_segment_min([(-10, 10), (1, 2), (3, 5)]) == [(-10, 10)]
assert cover_max_segment_min([(1, 2), (2, 3), (3, 4)]) == \
[(1, 2), (2, 3), (3, 4)]
assert cover_max_segment_min([(1, 4), (1, 2), (3, 3)]) == \
[(1, 4)]