nam*_*los 46 algorithm optimization performance geometry
-
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAA--------------BBB
AAAAAAAAAAAAAAAA--------------BBB
AAAAAAAAAAAAAAAA--------------BBB
AAAAAAAAAAAAAAAA--------------BBB
BBBBBBBBBBBBBBBBB
BBBBBBBBBBBBBBBBB
BBBBBBBBBBBBBBBBB
BBBBBB-----------CCCCCCCC
BBBBBB-----------CCCCCCCC
BBBBBB-----------CCCCCCCC
CCCCCCCCCCCCCCCCCCC
CCCCCCCCCCCCCCCCCCC
CCCCCCCCCCCCCCCCCCC
CCCCCCCCCCCCCCCCCCC
Run Code Online (Sandbox Code Playgroud)
Cam*_*lle 53
计算该区域的有效方法是使用扫描算法.让我们假设我们通过矩形U的并集扫描垂直线L(x):
我们仍然要解决一维问题.您需要一维结构,它动态计算(垂直)段的并集.通过动态,我的意思是你有时会添加一个新的段,有时会删除一个.
我已经在我对这个崩溃范围问题的答案中详细说明了如何以静态方式(实际上是一维扫描).因此,如果您想要一些简单的东西,您可以直接应用它(通过为每个事件重新计算联合).如果你想要更高效的东西,你只需要调整一下:
这是您的动态算法.假设您将使用带有日志时间位置查询的排序集来表示D 1 ... D k,这可能是您可以获得的最有效的非专业方法.
Lep*_*R64 10
这是我在TopCoder SRM 160 Div 2中使用的一些快速而脏的代码.
t = top
b = botttom
l = left
r = right
public class Rect
{
public int t, b, l, r;
public Rect(int _l, int _b, int _r, int _t)
{
t = _t;
b = _b;
l = _l;
r = _r;
}
public bool Intersects(Rect R)
{
return !(l > R.r || R.l > r || R.b > t || b > R.t);
}
public Rect Intersection(Rect R)
{
if(!this.Intersects(R))
return new Rect(0,0,0,0);
int [] horiz = {l, r, R.l, R.r};
Array.Sort(horiz);
int [] vert = {b, t, R.b, R.t};
Array.Sort(vert);
return new Rect(horiz[1], vert[1], horiz[2], vert[2]);
}
public int Area()
{
return (t - b)*(r-l);
}
public override string ToString()
{
return l + " " + b + " " + r + " " + t;
}
}
Run Code Online (Sandbox Code Playgroud)
Ros*_*one 10
import numpy as np
A = np.zeros((100, 100))
B = np.zeros((100, 100))
A[rect1.top : rect1.bottom, rect1.left : rect1.right] = 1
B[rect2.top : rect2.bottom, rect2.left : rect2.right] = 1
area_of_union = np.sum((A + B) > 0)
area_of_intersect = np.sum((A + B) > 1)
Run Code Online (Sandbox Code Playgroud)
在这个例子中,我们创建了两个零矩阵,它们是画布的大小.对于每个矩形,使用矩形占据空间的矩阵填充其中一个矩阵.然后总结矩阵.现在sum(A+B > 0)是联盟的区域,并且sum(A+B > 1)是重叠的区域.此示例可以很容易地推广到多个矩形.
这是我的头顶听起来像它可能工作的东西:
创建一个带有双键的字典,以及一个矩形+布尔值列表,如下所示:
Dictionary <Double,List <KeyValuePair <Rectangle,Boolean >>> rectangles;
对于集合中的每个矩形,找到x0和x1值的相应列表,并将矩形添加到该列表,对于x0,布尔值为true,对于x1,布尔值为false.这样,您现在可以获得每个矩形进入(true)或离开(false)x方向的所有x坐标的完整列表
从该字典中获取所有键(所有不同的x坐标),对它们进行排序,然后按顺序循环它们,确保您既可以获得当前的x值,也可以获得下一个x值(您需要它们两者) ).这为您提供了单独的矩形条带
例如,5个矩形,从a到e绘制在彼此之上:
aaaaaaaaaaaaaaaa bbbbbbbbbbbbbbbbb
aaaaaaaaaaaaaaaa bbbbbbbbbbbbbbbbb
aaaaaaaaaaaaaaaa bbbbbbbbbbbbbbbbb
aaaaaaaaaaaaaaaa bbbbbbbbbbbbbbbbb
aaaaaaaadddddddddddddddddddddddddddddbbbbbb
aaaaaaaadddddddddddddddddddddddddddddbbbbbb
ddddddddddddddddddddddddddddd
ddddddddddddddddddddddddddddd
ddddddddddddddeeeeeeeeeeeeeeeeee
ddddddddddddddeeeeeeeeeeeeeeeeee
ddddddddddddddeeeeeeeeeeeeeeeeee
ccccccccddddddddddddddeeeeeeeeeeeeeeeeee
ccccccccddddddddddddddeeeeeeeeeeeeeeeeee
cccccccccccc eeeeeeeeeeeeeeeeee
cccccccccccc eeeeeeeeeeeeeeeeee
cccccccccccc
cccccccccccc
Run Code Online (Sandbox Code Playgroud)
这是x坐标列表:
v v v v v v v v v
|aaaaaaa|aa|aaaa | bbbbbbbbbb|bb|bbb
|aaaaaaa|aa|aaaa | bbbbbbbbbb|bb|bbb
|aaaaaaa|aa|aaaa | bbbbbbbbbb|bb|bbb
|aaaaaaa|aa|aaaa | bbbbbbbbbb|bb|bbb
|aaaaaaaddd|dddddddddd|ddddddddddddddbb|bbb
|aaaaaaaddd|dddddddddd|ddddddddddddddbb|bbb
| ddd|dddddddddd|dddddddddddddd |
| ddd|dddddddddd|dddddddddddddd |
| ddd|ddddddddddeeeeeeeeeeeeeeeeee
| ddd|ddddddddddeeeeeeeeeeeeeeeeee
| ddd|ddddddddddeeeeeeeeeeeeeeeeee
ccccccccddd|ddddddddddeeeeeeeeeeeeeeeeee
ccccccccddd|ddddddddddeeeeeeeeeeeeeeeeee
cccccccccccc eeeeeeeeeeeeeeeeee
cccccccccccc eeeeeeeeeeeeeeeeee
cccccccccccc
cccccccccccc
Run Code Online (Sandbox Code Playgroud)
列表将是(其中每个v简单地给出一个从0开始向上的坐标):
0: +a, +c
1: +d
2: -c
3: -a
4: +e
5: +b
6: -d
7: -e
8: -b
Run Code Online (Sandbox Code Playgroud)
因此每个条带(从上到下排列的矩形):
0-1: a, c
1-2: a, d, c
2-3: a, d
3-4: d
4-5: d, e
5-6: b, d, e
6-7: b, e
7-8: b
Run Code Online (Sandbox Code Playgroud)
对于每个条带,重叠将是:
0-1: none
1-2: a/d, d/c
2-3: a/d
3-4: none
4-5: d/e
5-6: b/d, d/e
6-7: none
7-8: none
Run Code Online (Sandbox Code Playgroud)
我想,上下检查的sort + enter/leave算法的变体也是可行的:
对于上面的1-2条,你会像这样迭代:
0. empty set, zero sum
1. enter a, add a to set (1 rectangle in set)
2. enter d, add d to set (>1 rectangles in set = overlap, store this y-coordinate)
3. leave a, remove a from set (now back from >1 rectangles in set, add to sum: y - stored_y
4. enter c, add c to set (>1 rectangles in set = overlap, store this y-coordinate)
5. leave d, remove d from set (now back from >1 rectangles in set, add to sum: y - stored_y)
6. multiply sum with width of strip to get overlapping areas
Run Code Online (Sandbox Code Playgroud)
你实际上不必在这里维持一个实际的集合,只需要你在里面的矩形的数量,每当从1到2,存储y,并且每当它从2下降到1时,计算当前的y - 存储y,并总结这个差异.
希望这是可以理解的,正如我所说,这是我的头脑,没有以任何方式进行测试.