我搜索了很多,但我没有找到适合这种情况的好答案。 我们有一些水平或垂直的矩形。它们可以随机放在页面上。它们可以重叠或具有共同边缘或彼此分开。 我想找到一个带有O(nlogn)的算法,它可以找到这些矩形的周长和面积。 这些图片可能会使问题变得清晰。
我认为间隔树可能有所帮助,但我不确定如何。
答案 0 :(得分:8)
可以通过扫描线算法完成。
我们将从左到右扫描一条假想线。 我们会注意到直线和矩形集之间的交点表示一组间隔的方式,当我们遇到矩形的左边或右边时它会发生变化。
假设交点在x坐标 x1 和 x2 之间没有变化。 然后,如果 x1 之后的交点长度为 L ,则该线将扫过等于( x2 - x1的区域)* L ,从 x1 扫描到 x2 。
例如,您可以将 x1 视为左侧蓝线,将 x1 视为下图中的右侧蓝线(我从您那里偷走并修改一点点 :)):
应该清楚的是,我们的扫描线的交点在这些点之间没有变化。然而,蓝色交叉点与红色交叉点完全不同。
我们需要一个包含这些操作的数据结构:
insert_interval(y1, y2);
get_total_length();
使用分段树可以很容易地实现这些功能,所以我现在不会详细介绍。
现在,算法将如下所示:
通过左和右我的意思是矩形的边。
这个想法仅用于计算区域,但是,您可以修改它以计算周长。基本上你会想知道交叉点在某个x坐标处变化之前和之后的长度之间的差异。
算法的复杂性为O(N log N)(尽管它取决于您可能获得的值的范围,这很容易处理)。
您可以在TopCoder上找到有关扫描线算法这一广泛主题的更多信息。
您可以在PEG judge wiki上阅读有关使用细分树的各种方法。
这是我(非常古老)算法的实现,作为SPOJ problem NKMARS:implementation的解决方案。
答案 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;
}