找到由m个矩形中的n个覆盖的区域的边界

时间:2013-11-04 15:32:33

标签: dynamic-programming

我有一组m个非旋转,整数(像素)对齐的矩形,每个矩形可能重叠也可能不重叠。矩形覆盖数千个像素。我需要找到覆盖m个矩形中n个所覆盖的所有区域的最小大小的边界框。

这样做(脏)的方法是绘制一个覆盖所有目标区域的画布。这是O(mk),其中m是矩形的数量,k是每个矩形的像素数。然而,由于k远大于m,我认为有更好的解决方案。

这感觉就像一个动态的编程问题......但是我无法弄清楚递归。

解决方案哪个更好但仍然不是很好:

对X方向上的所有矩形的起点和终点O(mlogm)进行排序,迭代并找到可能有超过n个矩形的x位置,O(m)循环。对于可能有n个以上矩形的每个x位置,取该位置的矩形并对该位置的起点和终点进行排序(O(mlogm))。找到重叠区域,跟踪那条路的边界。总的来说,O(m ^ 2logm)。

4 个答案:

答案 0 :(得分:1)

Hello MadScienceDreams,

为了澄清,边界框也是非旋转的,对吗?

如果是这种情况,那么只需跟踪四个变量:minX, maxX, minY, maxY - 表示定义边界框的最左侧,最右侧,最顶部和最底部像素,循环通过每个矩形更新四个变量,并在给定这四个变量的情况下定义新的边界框。

修改

看起来你问的是找到某些矩形子集的边界,而不是整个集合。

所以你有M个矩形,然后从中选择N个矩形,找到其中的边界。

即使在这种情况下,循环N个矩形并跟踪它们的界限最多也是O(m),这一点都不差。

我觉得我必须误解你的问题,因为这个回答不是你可能想要的;你的问题实际上是试图询问如何预先计算边界,以便给定任何子集,知道恒定时间内的总界限?

答案 1 :(得分:0)

这是否定义了您的问题?对于边界框 => #rect_label >= n Bounding Box

答案 2 :(得分:0)

我们如何从一个盒子开始,找到距离它最近的最近一个角落的下一个盒子。现在我们有一个有两个盒子的区域。递归地找到下一个区域,直到我们有n个框。

虽然我们需要从每个盒子开始,但我们只需要积极地处理当前最小的区域。效果是我们从最小的盒子集群开始,然后从那里扩展出来。

如果n更接近m而不是0,我们可以反转搜索树,以便从全方位封闭框开始,切断每个边框以创建下一个搜索级别。假设我们只是积极地处理剩余的最小区域,那么我们首先要切断最空的区域。

太复杂了吗?对不起,我记不住这次搜索的名字了。我不擅长数学,所以我会跳过O符号。 > _<

答案 3 :(得分:0)

我提出以下算法:

prepareData();
if (findBorder('left')) {
     foreach (direction in ['top', 'right', 'bottom']) {
         findBorder(direction)
    }
} else noIntersectionExists

prepareData(O(mlogm)):
订购垂直边界和水平边界
将结果保存为:
      - 两个指向矩形的数组(arrX和arrY)
      - 将索引保存为矩形的属性(rectangle.leftIndex,rectangle.topIndex等

findBorder(左)://其他方向相似 最佳情况O(n),最坏情况O(2m-n)

arrIntersections = new Array;
//an intersection has a depth (number of rectangles intersected), a top and bottom border and list of rectangles
for(i=0; i < 2*m-n-1; i++){ // or (i = 2*m-1; i > n; i--)
    if(isLeftBorder(arrX[i])){
        addToIntersections(arrX[i].rectangle, direction);
        if(max(intersections.depth) = n) break;
    } else {
        removeFromIntersections(arrX[i].rectangle, direction);
    }
}

addToIntersections(矩形,方向)://对direction = left的解释 最佳情况:O(n),最坏情况:O(m)

hasIntersected = false;
foreach(intersection in intersection){
    if(intersect(intersection, rectangle)){
        hasIntersected = true
        intersections[] = {
            depth: intersection.depth,
            bottom: min(intersection.bottom, rectangle.bottom),
            top: max(...)}
        intersection.depth++
        intersection.bottom = max(intersection.bottom, rectangle.bottom)
        intersection.top = max(...)
    }
}
if(!hasIntersected)
    intersections[]={depth:1, bottom:rectangle.bottom, top:rectangle.top}

这给出了O(n ^ 2)和O(m *(m-n / 2))之间的整体顺序

我希望我的伪代码足够清晰