计算相交矩形的周长和面积?

时间:2013-01-24 16:07:27

标签: algorithm tree intervals

我搜索了很多,但我没有找到适合这种情况的好答案。 我们有一些水平或垂直的矩形。它们可以随机放在页面上。它们可以重叠或具有共同边缘或彼此分开。 我想找到一个带有O(nlogn)的算法,它可以找到这些矩形的周长和面积。 这些图片可能会使问题变得清晰。

enter image description here

我认为间隔树可能有所帮助,但我不确定如何。

2 个答案:

答案 0 :(得分:8)

可以通过扫描线算法完成。

我们将从左到右扫描一条假想线。 我们会注意到直线和矩形集之间的交点表示一组间隔的方式,当我们遇到矩形的左边或右边时它会发生变化。

假设交点在x坐标 x1 x2 之间没有变化。 然后,如果 x1 之后的交点长度为 L ,则该线将扫过等于( x2 - x1的区域)* L ,从 x1 扫描到 x2

例如,您可以将 x1 视为左侧蓝线,将 x1 视为下图中的右侧蓝线(我从您那里偷走并修改一点点 :)): enter image description here

应该清楚的是,我们的扫描线的交点在这些点之间没有变化。然而,蓝色交叉点与红色交叉点完全不同。

我们需要一个包含这些操作的数据结构:

insert_interval(y1, y2); 
get_total_length(); 

使用分段树可以很容易地实现这些功能,所以我现在不会详细介绍。

现在,算法将如下所示:

  1. 获取所有垂直线段并按x坐标对其进行排序。
  2. 对于每个相关的x坐标(仅显示为矩形边缘的那些坐标很重要):
    • 设x1为先前的相关x坐标。
    • 设x2为当前相关的x坐标。
    • 设L是我们的数据结构给出的长度。
    • 将(x2 - x1)* L添加到总面积总和中。
    • 从数据结构中删除x = x2段的所有边。
    • 将x = x2段的所有边添加到数据结构中。
  3. 通过我的意思是矩形的边。

    这个想法仅用于计算区域,但是,您可以修改它以计算周长。基本上你会想知道交叉点在某个x坐标处变化之前和之后的长度之间的差异。

    算法的复杂性为O(N log N)(尽管它取决于您可能获得的值的范围,这很容易处理)。

    您可以在TopCoder上找到有关扫描线算法这一广泛主题的更多信息。

    您可以在PEG judge wiki上阅读有关使用细分树的各种方法。

    这是我(非常古老)算法的实现,作为SPOJ problem NKMARSimplementation的解决方案。

答案 1 :(得分:0)

以下是O(N2)溶液。

int area = 0;
FOR(triange=0->N)
{
    Area = area trianlges[triangle];
    FOR(int j = triangle+1 -> N)
    {
        area-= inter(triangle , j)
    }
}
return area;

int inter(tri a,tri b)
{
    if ( ( min(a.highY ,b.highY) > max(a.lowerY, b.lowerY) ) && ( min(a.highX ,b.highX) > max(a.lowerX, b.lowerX) ) )
    return ( min(a.highY ,b.highY) - max(a.lowerY, b.lowerY) ) * ( min(a.highX ,b.highX) - max(a.lowerX, b.lowerX) )

    else return 0;
}