这可以通过线扫描算法解决吗?

时间:2013-04-06 17:06:00

标签: algorithm

编辑:现在我认为这是扫描线问题。 (见底部的update2)

在这个问题中,我们给出了N个对象和M个约束。 (N可以是200kM可以是100k)。每个对象都是黑色或白色。每个约束的格式为(x, y),表示在对象范围x..y中,只有一个白色对象;其余的都是黑色的。我们想确定可以存在的最大白色对象数,或者是否无法满足约束条件。

我观察到如果约束完全包含在另一个约束中,则内部约束将指示可以放置白色对象的位置。此外,如果在另一个中包含多个非交叉约束,则应该是不可能的,因为它违反了每个约束只能有一个白色对象的事实。该算法应该足够快,可以在2-3秒内运行。

更新:其中一个答案提到确切的封面问题;这是一个非NP完全的专门实例吗?

Update2:如果我们将每个约束更改为 begin end 事件,并对这些事件进行排序,我们是否可以系统地扫描这些事件并分配白色对象?< / p>

2 个答案:

答案 0 :(得分:2)

你的问题可以表示为exact cover problem:约束区间形成要覆盖的集合,每个白色对象覆盖它所属的那些约束区间。那么,你的问题是找到一个白色物体的子集,它只覆盖每个约束间隔一次。

确切的覆盖问题通常是NP完全的,尽管这显然不一定意味着它们的任何特定子集。但是,仍然存在一些算法,例如Knuth's Algorithm X(由dancing links实现),可以非常有效地解决大多数此类问题。

问题的一维结构可能也允许更直接的专业解决方法。但是,算法X是用于攻击此类问题的非常好的通用工具。 (例如,最快sudoku solvers通常使用类似的东西。)

答案 1 :(得分:1)

是的,有一个(点) - 扫描算法。这个有点不优雅,但我认为它有效。

首先,扫描嵌套间隔。按排序顺序处理开始和结束事件(断路器留给您)并保留一个未知包含另一个间隔的活动间隔列表。要处理begin事件,请附加相应的间隔。要处理结束事件,请检查是否已删除相应的间隔I。如果没有,请从列表中删除I以及J之前的所有剩余时间间隔I。对于每个此类J,将两个间隔(其并集是设置差异J \ I)附加到黑色间隔列表中。

第二,扫除收缩黑暗间隔。换句话说,删除已知为黑色的对象,重新编号,并相应地调整约束。如果整个约束被涂黑,则没有解决方案。

第三,扫描以解决现在非嵌套间隔的问题。贪婪的解决方案可证明是最佳的。

示例:假设我有半开约束[0,4],[1,3],[2,5]。第一次扫描会产生停电[0,1]和[3,4]。第二次扫描留下约束[a,c),[a,c),[b,d)。*贪婪扫描将白色物体放置在新位置a,c,d(旧位置1,4,5)。

第二次扫描的插图:

0 1 2 3 4 5  old coordinates
[       )
  [   )
    [     )
**    **     blackouts
  a b   c d  new coordinates
[       )
  [   )
    [     )