基线位于x轴上的最大空矩形

时间:2015-10-02 06:58:46

标签: algorithm computational-geometry rectangles

Original Problem: Problem 2

在高度为500且宽度为10 ^ 5的矩形空间中,我们给出了N个点。

我们应该找出最大的子矩形,其基部位于x轴上,并且不包含其正确内部的任何点(但可以在其边缘包含它们)。

我尝试了一种O(宽度^ 2)算法:

#include <iostream>
#include <algorithm>

const int nWidth = 100000;
const int nHeight = 500;

int main(){

  int *nMaxHeights = new int[nWidth];
  std::fill (nMaxHeights, nMaxHeights+nWidth, nHeight);

  int N;
  std::cin >> N;
  for (int x,y,iii=0; iii < N; iii++){
    std::cin >> x >> y;
    nMaxHeights[x] = std::min(y+1, nMaxHeights[x]);
  }

  int maxArea = 0;
  for (int jjj,iii=0; iii < nWidth; iii++){
    for (jjj=iii; jjj < nWidth; jjj++){
      if (nMaxHeights[jjj] < nMaxHeights[iii])
        break;
    }
    maxArea = std::max((jjj-iii+1)*nMaxHeights[iii],maxArea);
  }

  std::cout << maxArea;   

  return 0;
}

它有效,但显然收到TLE(超出执行时间限制)。

我该怎么做得更好?

2 个答案:

答案 0 :(得分:0)

有趣的问题。谢谢你指出这些。

我使用了一种算法,可以将O(N)缩放为较大的N(点数)和随机分布点。背后的想法:每个矩形都会受到一些点的限制。

  1. 如果一个x值有更多的点,则只使用y值最小的一个。
  2. 首先检查极端x点;最左边和最左边,跨越一个矩形到resp。限制。
  3. 然后去最右边的点并尝试构建一个包含它的矩形。有两种可能性:
    1. 此点位于水平边缘:找到具有较低y值的左右两个邻居,并将它们用作左侧的点。右边缘。如果没有左/右邻居,请使用空格的末尾。
    2. 此点位于垂直边缘:找到左下角的点,使用空格的(y-)限制作为水平边缘。
  4. 对于每个点,计算可能的矩形区域(上面两种可能),如果任何大于当前最大区域,则更新最大区域。
  5. 以下是python中的一些示例实现http://pastebin.com/068ByYwh,但我不是肯定的,它不包含错误; - )

答案 1 :(得分:0)

想象一下。有三种可能的矩形:在点的下方,左侧和右侧。

我们现在说有两点。让我们先看一下靠近底部的那个。同样,这一步有三种情况。这一点下方有一个矩形。在另一个点的相对侧还有一个矩形。还有另一个点的一面,那里有更多的矩形。

IOW,如果从底部向上看点,那么每个点下面都有一个矩形,这个点将空间分成两个垂直带,每个带有其他点,下面同样有矩形,进一步细分空间。

因此,通过Y和X对点进行排序似乎是合理的(可能通过使它们成为两个排序树的节点,一个按Y排序(因此可以在Y中向上移动)而另一个按X排序(所以你可以移动/搜索左/右)),这是N * log(N),然后递归地访问所有点自下而上,适当地细分空间,看起来像另一个N * log(N)。