【问题标题】:Find two rectangles with minimum areas that cover all points找到两个覆盖所有点的面积最小的矩形
【发布时间】:2018-05-01 04:30:05
【问题描述】:

给你一个 n 点,在一个数组中未排序。你应该找到两个覆盖所有点的矩形,它们不应该重叠。矩形的边缘应平行于 x 或 y 纵坐标。
该程序应返回所有这些点所覆盖的最小区域。第一个矩形的面积 + 第二个矩形的面积。

我试图解决这个问题。我按 X 纵坐标对点进行排序,第一个是第一个矩形的最左侧。当我们遍历这些点时,我们会找到最高点和最低点。我在想,当 x 两点之间的差异最大时,这意味着第一个点是第一个矩形的最右边,第二个点是第二个矩形的最左边的一个。
它应该在第一个示例中给出点时起作用,但是,如果该示例是第二个示例,则它不起作用。因为它会返回这样的东西,这是错误的:

这应该是正确的:


然后我想进行两次排序,只是,第二次按 Y 坐标进行,然后比较两个总区域。点按 x 排序和点按 y 排序时的区域,较小的区域是正确答案。

【问题讨论】:

  • 那么您对我们有什么期望?这个问题中的“溢出”(您尝试过并停留在某个地方)在哪里?
  • 我更新了问题
  • 这是来自编码竞赛的问题吗?你能提供一个比赛的链接吗?
  • 即使在您更新之后,也不清楚是什么问题。 你尝试过你想做的事情吗?结果是你想要的吗?
  • 这是轴平行两个矩形点集覆盖问题的变体,其中一个 O(nlogn) 解决方案发表在“Covering a set of point by two axis-parallel boxes”[贝斯帕米亚特尼克,西格尔 2000]。在这个问题中,最小化的函数是(以及其他替代方案)较大矩形的面积,而在您的问题中,应该最小化的函数是矩形面积的总和。

标签: algorithm geometry computational-geometry


【解决方案1】:

第一个观察是矩形的任何边缘都必须接触其中一个点。未接触点的边缘可能会被拉回,从而减少面积。

给定 n 个点,因此 left1、right1、bottom1、top1、left2、right2、bottom2 和 top2 总共有 n 个选择。这已经给出了一个简单的 O(n^8) 算法:尝试所有可能的分配并记住总面积最小的分配 (right1 - left1)(top1 - bottom1) + (right2 - left2)(top2 - bottom2)。实际上,您可以跳过右

另一个观察结果是边缘应保持在所有点的最小和最大 X 和 Y 范围内。找出任何点的最小和最大 X 和 Y 值。调用这些 minX、maxX、minY 和 maxY。至少有一个矩形需要在这些级别分别具有左、右、下和上边缘。

因为必须将 minx、maxX、minY 和 maxY 分配给两个矩形之一,并且恰好有 2^4 = 16 种方法可以做到这一点,所以您可以尝试四种可能的分配方式,其余坐标分配为更多。这给出了一个 O(n^4) 算法:O(n) 得到 minX、maxX、minY 和 maxY,然后 O(n^4) 为 minX、maxX 的 16 个赋值中的每一个填充四个未赋值变量, minY 和 maxY 到八个边缘坐标。

到目前为止,我们忽略了矩形不重叠的要求。为了适应这种情况,我们必须确保至少满足以下四个条件之一:

  1. 在 Y 坐标 h 的水平线与 top1
  2. 在 Y 坐标 h 的水平线与 top2
  3. 在 X 坐标 w 的一条垂直线与 right1
  4. X 坐标 w 处的一条垂直线,right2

当且仅当所有这四个条件都为假时,两个矩形才会重叠。这允许我们跳过候选解决方案,提供加速但不改变渐近界 O(n^4)。请注意,我们需要特别检查这个条件,否则最优解可能会重叠(练习:展示这样的示例)。

让我们试着缩短一些时间。假设我们在上面的条件 #1 中有不重叠的矩形。那么h有n个选择;我们可以尝试这 n 个选择中的每一个,然后通过找到结果半部分中点的最小和最大坐标来确定结果选择的区域。通过对 h 尝试所有 n 个选择,我们可以确定“最佳情况”垂直分割。我们不需要尝试条件 #2,因为唯一的区别在于矩形的顺序是任意的。我们还必须尝试使用​​水平分割的条件 #3。这建议使用 O(n^2) 算法:

  1. 对于每个点,选择 h = point.y
  2. 使用 point.y h 将点分成组。
  3. 找出两个点子集的最小和最大 X 和 Y 坐标。
  4. 计算两个矩形的面积之和。
  5. 记住上面得到的最小面积和对应的h。
  6. 重复,但使用 w 和 X 坐标。
  7. 确定是否获得了垂直或水平分割的最小面积
  8. 返回对应的矩形作为答案

我们还能做得更好吗?这是 O(n^2) 而不是 O(n),因为对于 h 和 w 的每个选择,我们需要找到每个子组的最小和最大坐标。这假设对两个子组进行线性扫描。在水平/垂直扫描时,我们实际上不需要对最小和最大 X/Y 坐标执行此操作,因为这些都是已知的。我们需要的是解决这个问题:

给定n个点和一个值h,求Y坐标不大于h的任意点的最大X坐标。

我在上面给出的显而易见的解决方案是 O(n^2),但是您可以通过巧妙地应用排序来找到 O(n log n) 解决方案,或者甚至可以通过更多的解决方案找到 O(n) 解决方案聪明的方法。我不会尝试这个。

我们的解决方案是 O(n^2);理论上最佳解决方案是 Omega(n),因为您至少必须查看所有点。所以我们已经很接近了,但还有改进的空间。

【讨论】:

    【解决方案2】:

    两个矩形不能重叠,因此一个必须完全在右侧或在另一个之上。您按 x 值对点进行排序并找到最大差距的想法很好,但您应该按照您的建议对两个方向都这样做。这将在您的示例中找到正确的矩形。

    然而,最大的差距不一定是理想的分裂点。根据边界框在垂直方向上的范围,分割可能在其他地方。考虑一个有四个象限的矩形区域,其中两个对角相对的象限用点填充:

    在这里,理想的分割不是最大的差距。

          

    您可以通过考虑具有相邻 x 和 y 坐标的点之间的所有可能分割来找到理想位置。

    • 按 x 坐标对点进行排序。
    • 按升序扫描已排序的数组。通过存储最小和最大 y 坐标来跟踪当前点左侧的最小矩形。为每个点存储这些运行的顶部和底部边框。
    • 现在按降序执行相同的操作,继续为右侧矩形设置顶部和底部边框。
    • 最后,再次循环遍历这些点并计算左右最小矩形的面积,以便在两个相邻节点之间进行分割。跟踪最小面积总和。

    然后对最小的顶部和底部矩形执行相同的操作。最后两个步骤可以合并,这将保存右侧矩形的最小边界的数组。

    这应该是 O(n · log n) 的时间:排序是 O(n · log n) 并且单个通过是 O(n)。您需要 O(n) 额外内存来运行第一个矩形的边界框。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2012-12-25
      • 1970-01-01
      • 2011-03-29
      • 1970-01-01
      • 2012-07-25
      • 2011-06-30
      • 2011-06-02
      相关资源
      最近更新 更多