我似乎无法找到一种方法来在标题中编写算法,而无需以某种方式来整理结果。
为了说明我想要的:
all_spans = [(0, 5), (2, 7), (5, 8), (6, 10), (9, 10), (11, 15)]
possible_sets = [
{(0, 5), (5, 8), (9, 10), (11, 15)},
{(2, 7), (9, 10), (11, 15)},
{(0, 5), (6, 10), (11, 15)}
]
not_possible = [
{(0, 5), (5, 8), (6, 10), (11, 15)}, # has overlaps
{(5, 8), (9, 10), (11, 15)} # not maximal w.r.t possible_sets[0]
]
我目前的实现方式或多或少是这样的:
def has_overlap(a, b):
return a[1] > b[0] and b[1] > a[0]
def combine(spans, current, idx=0):
for i in range(idx, len(spans)):
overlaps = {e for e in current if has_overlap(e, spans[i])}
if overlaps:
yield from combine(spans, current-overlaps, i)
else:
current.add(spans[i])
yield current
但是它会产生非最大跨度,我宁愿先不创建跨度。
>>> for s in combine(all_spans, set()):
... print(sorted(s))
[(9, 10), (11, 15)]
[(6, 10), (11, 15)]
[(5, 8), (9, 10), (11, 15)]
[(9, 10), (11, 15)]
[(6, 10), (11, 15)]
[(2, 7), (9, 10), (11, 15)]
[(0, 5), (9, 10), (11, 15)]
[(0, 5), (6, 10), (11, 15)]
[(0, 5), (5, 8), (9, 10), (11, 15)]
是否有避免这种行为的其他方法?我在关键字“时间间隔重叠”和“活动计划”下发现了类似的问题,但是似乎没有一个问题涉及到此特定问题。
答案 0 :(得分:2)
这取决于您不希望整理结果的意思。
将生成器与以下各项配合使用后,您可以滤除非最大结果:
all_results = [s for s in combine(all_spans, set())]
for first_result in list(all_results):
for second_result in list(all_results):
if first_result.issubset(second_result) and first_result != second_result:
all_results.remove(first_result)
break
如果不首先生成它们,可以在屈服之前进行检查以查看答案是否最大。像这样:
def combine(spans, current, idx=0):
for i in range(idx, len(spans)):
overlaps = {e for e in current if has_overlap(e, spans[i])}
if overlaps:
yield from combine(spans, current-overlaps, i)
else:
current.add(spans[i])
# Check whether the current set is maximal.
possible_additions = set(spans)
for item_to_consider in set(possible_additions):
if any([has_overlap(item_in_current, item_to_consider) for item_in_current in current]):
possible_additions.remove(item_to_consider)
if len(possible_additions) == 0:
yield current
答案 1 :(得分:1)
这是一个简单的(?)曲线图的问题。制作一个有向图,其中每个跨度都是一个节点。假说,如果跨度B在跨度A完成之前没有开始,那么存在A边(从节点A到节点B)iff A [1] <= B [0]。你的图形看起来就像
Node => Successors
(0, 5) => (5, 8), (6, 10), (9, 10), (11, 15)
(2, 7) => (9, 10), (11, 15)
(5, 8) => (9, 10), (11, 15)
(6, 10) => (11, 15)
(9, 10) => (11, 15)
现在,问题减少到只需要查找图中的最长路径(包括领带)即可。
鉴于问题的线性,找到一个最大的解比较容易:在每个步骤中,选择终止时间最快的后继节点。步骤:
请注意,此多不需要的曲线图。仅仅是一个结构你愿意通过第一或第二子元件参考。
您已经知道,解决方案的长度为4。
你能走在这里形成的?
答案 2 :(得分:0)
假定范围是按下限排序的,我们想将当前范围附加到可以附加的最长路径上,或创建一个新路径(附加到空路径上)。如果需要,我们可以考虑使搜索最长前缀的效率更高。 (下面的代码只是以稍微优化的线性方法更新搜索。)
(我不确定如何使用yield功能,也许您可以使此代码更加优雅。)
# Assumes spans are sorted by lower bound
# and each tuple is a valid range
def f(spans):
# Append the current span to the longest
# paths it can be appended to.
paths = [[spans.pop(0)]]
for l,r in spans:
to_extend = []
longest = 0
print "\nCandidate: %s" % ((l,r),)
for path in paths:
lp, rp = path[-1]
print "Testing on %s" % ((lp,rp),)
if lp <= l < rp:
prefix = path[:-1]
if len(prefix) >= longest:
to_extend.append(prefix + [(l,r)])
longest = len(prefix)
# Otherwise, it's after so append it.
else:
print "Appending to path: %s" % path
path.append((l, r))
longest = len(path)
for path in to_extend:
print "Candidate extensions: %s" % to_extend
if len(path) == longest + 1:
print "Adding to total paths: %s" % path
paths.append(path)
print "\nResult: %s" % paths
return paths
all_spans = [(0, 5), (2, 7), (5, 8), (6, 10), (9, 10), (11, 15)]
f(all_spans)
输出:
"""
Candidate: (2, 7)
Testing on (0, 5)
Candidate extensions: [[(2, 7)]]
Adding to total paths: [(2, 7)]
Candidate: (5, 8)
Testing on (0, 5)
Appending to path: [(0, 5)]
Testing on (2, 7)
Candidate: (6, 10)
Testing on (5, 8)
Testing on (2, 7)
Candidate extensions: [[(0, 5), (6, 10)]]
Adding to total paths: [(0, 5), (6, 10)]
Candidate: (9, 10)
Testing on (5, 8)
Appending to path: [(0, 5), (5, 8)]
Testing on (2, 7)
Appending to path: [(2, 7)]
Testing on (6, 10)
Candidate: (11, 15)
Testing on (9, 10)
Appending to path: [(0, 5), (5, 8), (9, 10)]
Testing on (9, 10)
Appending to path: [(2, 7), (9, 10)]
Testing on (6, 10)
Appending to path: [(0, 5), (6, 10)]
Result: [[(0, 5), (5, 8), (9, 10), (11, 15)],
[(2, 7), (9, 10), (11, 15)],
[(0, 5), (6, 10), (11, 15)]]
"""