Algorithm 如何在O(nlogn)中找到相交线的上包络线?

Algorithm 如何在O(nlogn)中找到相交线的上包络线?,algorithm,geometry,computational-geometry,analysis,Algorithm,Geometry,Computational Geometry,Analysis,免责声明:是的,这是一个家庭作业,我想了几天,但找不到一条路走 所以有n条直线(y=ax+b),我想找到它们的上封套(图中粗体部分)。它必须处于O(nlogn)状态 我的理解是,我需要找到一种方法来忽略一些行,因为如果我搜索所有行,它将不会是O(nlogn) 我正在考虑一种分而治之的方法,这样我可以将列表一分为二,然后递归地继续,直到找到解决方案。但我不知道如何摆脱一些台词。显然,我不需要考虑图片中的一些底线,因为他们不可能为解决方案做出贡献。但我什么也没想到。如有任何提示,我们将不胜感激 如果

免责声明:是的,这是一个家庭作业,我想了几天,但找不到一条路走

所以有n条直线(y=ax+b),我想找到它们的上封套(图中粗体部分)。它必须处于O(nlogn)状态

我的理解是,我需要找到一种方法来忽略一些行,因为如果我搜索所有行,它将不会是O(nlogn)

我正在考虑一种分而治之的方法,这样我可以将列表一分为二,然后递归地继续,直到找到解决方案。但我不知道如何摆脱一些台词。显然,我不需要考虑图片中的一些底线,因为他们不可能为解决方案做出贡献。但我什么也没想到。如有任何提示,我们将不胜感激


如果我看得对的话,行总是按照其“a”值的顺序贡献给“信封”。因此,请按a排序。如果有两个a相同,它们是平行的,b决定哪个在另一个之上(你可以忽略较低的)。如果你知道直线的顺序,你可以计算O(1)中两条连续直线的交点。所以基本上这只是排序,这就是O(n logn)

编辑:好的,其中一条评论是正确的-没有平行线不分布到信封-原因是它们会对信封的影响超过拐点。但包络线段按其“a”的顺序从直线开始的事实仍然正确(这意味着始终有起始段和结束段)

问题是如何确定哪一行是信封的组成部分,哪一行不是。
在阵列上扫描一次以找到转折点(必须是“a”切换符号的位置)。从这里开始,一次下降(减少a),一次上升(增加a)。计算与下一条直线的交点-如果它位于错误的一侧(不是减少/增加)x,则跳过它。在排序后,删除平行线(等于a)的扫描仍应适用,因为在计算交点时,这忽略了病理情况

首先,我们为行构造两个不同的二叉搜索树,一个根据行的
a
排序,另一个根据行的
b
排序

现在我们开始考虑行
lmin
lmax
,它们是具有最小和最大
a
的行;它们肯定会有助于从与第二最小和第二最大直线的交点处获得点,我们将这两个点添加到上封套中


现在我们考虑了交叉口<代码>(席,易)<代码> >代码> >代码> LMAX < /代码>,我们理想地画出垂直<代码> x=席< /代码>行。现在我们必须确定在坐标

y0 s.t.y0中相交的线。提示:这个问题基本上是问题的对偶

解决方案:如果您将每条线
y=ax+b
视为一个点
(a,b)
,并在
(0,-无穷大)
处添加一个额外的“点”,您应该能够将其输入到任何2D凸包算法中,并获得正确的解

注:相反,此问题的任何解决方案也可用于构建相同O()的2D凸包算法


编辑:一个证明它的请求

对于一个点
(x,y)
位于一条特定直线的上方
y=ax+b
,你有一个不等式
ax-y+b>0

该不等式还等效于线
(-a,b)
上方的点
(b)=x(-a)+y
,其中x是斜率,y是截距

这使我们能够将点视为线,将线视为点:任何关于点和线的证明或算法都可以映射为一个同样有效的证明或算法,并将线和点反转

在这种情况下:一组2D点的凸包决定了不是其他点的凸包组合的“极值”点,以及连续极值点之间的直线。相应地,凸包的双重版本确定了那些不是其他凸包组合的“极值”线,以及连续极值线之间的交点。这是给定行集合的包络

凸包的对偶为您提供了输入线集的上包络和下包络。由于您只需要行的上封套,因此需要添加一条比任何可能的常规行都低的行,以消除下封套。或者,您可以查看解决方案并仅选择坡度增加的交点


相反,这个问题的任何解都可以用来确定一组点的上凸包。运行它两次,一次为{(a,b)}行,另一次为{(-a,-b)}行,将得到一个完整的凸包。

我不知道如何解决这个问题,但请注意,您确实知道最左边和最右边的行(因为x趋向于负无穷大和正无穷大),因为它们将具有最小和最大的
a
(当x变大时,
ax
支配
b
的任何值)


考虑到这一点,你可以找到它们相交的地方并丢弃该点下的线(我认为)。然后你可能会以某种方式进行迭代(例如,在交叉点的x坐标处找到最高的线,然后重复与原始两条线相交的两个点…。希望这会有所帮助。

我想象从(0,+无穷大)到我们的线集。光线的第一个碰撞点是我们封套的一部分。如果任何3个连续碰撞不是共线的,则会在碰撞点1和2以及2和3之间发送更多光线。对于击中同一条线的连续碰撞,只需在输出集中记录一条。然后,您将使用碰撞线集生成
R | L
1 | Line8
2 | Line2
3 | Line2
4 | Line1
R | L
1 | Line8
5 |  Line8 * culled out
6 |  Line8
7 |  Line5
8 |  Line2
2 | Line2 * culled out
3 | Line2 * culled out
9 |  Line2 * culled out
10|  Line2
11|  Line1
12|  Line1 * culled out
4 | Line1
for t = 0, 1, 2 ... do
     k = 2^(2^t)
     arbitrarily partition the segments into ceiling(n/k) subsets each of size at most k
     run any O(nlogn) time algorithm on each group yielding ceiling(n/k) monotone polygonal chains
     find the upper envelope of these monotone polygonal chains, and abort if the output size exceeds k
end for