【问题标题】:How to algorithmically find the biggest rectangle that can fit in a space with other rectangles?如何通过算法找到可以与其他矩形一起放入空间的最大矩形?
【发布时间】:2019-01-05 13:47:16
【问题描述】:

所以我有一个6m x 2.25m 的矩形,还有其他 4 个具有静态尺寸但随机放置在全局矩形内的矩形。

我需要一个函数来计算最大矩形的面积,该面积可以容纳在外部矩形中,也不会与其他矩形重叠。

我考虑过找到小矩形之间的最大 x 距离,但取决于它们是面向横向还是纵向,x 可能无法完成这项工作。在这一点上,我有点卡住了,我在网上找不到太多关于这样做的信息,但我确信这对于有经验的编码人员来说是一项相当普通的任务。

更新: 这是一个示例图像,以显示我要描述的内容。彩色矩形以静态尺寸随机放置,我想找到可以容纳的最大矩形。

感谢您的宝贵时间!

【问题讨论】:

  • 你的问题不太清楚。 “不会干扰其他矩形”是什么意思?结果矩形是否需要与全局矩形对齐?等等。请给出一个完整的输入示例和问题的更多描述。
  • 对不起,我应该更清楚。我所说的“不会干涉”是指它们不会相互影响。它们不能共享同一个空间——它们可以相邻但不能相互重叠。我只是包含了一个示例图像来帮助解释。让我知道我是否可以做更多的事情来尽可能清楚地说明这一点。
  • 该示例显示没有一个矩形重叠。总是这样吗?你能包含你自己的代码吗?
  • @HåkenLid 是正确的,没有一个矩形重叠。我的代码的哪一点?矩形放置还是面积计算?

标签: python algorithm rectangles area


【解决方案1】:

作为一个起点。时间和空间复杂度上较小矩形数量的二次方。

高级方法

1) 根据较小子矩形的尺寸(图中紫线)将大矩形划分为多个子矩形。最佳矩形的边界总是由这些子矩形组成。

2) 标记出不能成为最终结果的填充子矩形(图中的红色和黄色矩形)

3) 现在我们遇到了一个搜索问题。我们可以使用任何搜索算法(我使用的是 DFS)。您可以对此进行优化(例如缓存),但为简单起见:

伪代码

frontier = queue(all subrectangles)
largest_area = None

while frontier is not empty: 
    rectangle = pop a rectangle off frontier

    if all subrectangles to the right of rectangle are unoccupied:
        add (rectangle + extra subrectangles to the right) to frontier
        largest_area = max(area of new rectangle, largest_area)
    else if all subrectangles below rectangle are unoccupied:
        add (rectangle + extra subrectangles below) to the frontier
        largest_area = max(area of new rectangle, largest_area)

print largest_area

说明

说矩形是绿色矩形。可能的后续状态是添加带有蓝色星星的子矩形或添加带有粉红色星星的子矩形。然而,粉红色的星星与黄色的矩形重叠,所以我们不能添加它。

【讨论】:

  • 您能进一步解释explanation 部分吗?我对这实际上是如何工作的以及您在您的示例中“搜索”的内容感到困惑。
  • 你弄错了时间复杂度。搜索的每次迭代需要 O(N) 时间,有 O(N^2) 个子矩形,还有 O(N^4) 个矩形可以添加到边界,从而得到 O(N^5) 个解。将你的分解与stackoverflow.com/questions/2478447/… 结合起来得到一个真正的 O(N^2) 解决方案
【解决方案2】:

最佳矩形是它在四个边上接触其他矩形(否则你可以放大它)。因此,您将搜索限制为可用坐标。

蛮力解决方案可以如下工作:

  • 列出所有横坐标和纵坐标(包括外部界限)并逐步排序;

  • 对于每个(横坐标,纵坐标)组合,找到以该点为左上角的最大矩形,如下:

    • 对于每一个(横坐标',纵坐标')组合,使得横坐标' > 横坐标和纵坐标' > 纵坐标,使用该点作为矩形的右下角,并进行如下测试:

      • 对于每个给定的矩形,检查它是否与被测矩形重叠;如果有重叠,则忽略此候选。

      • 如果没有重叠,则接受候选人;计算它的面积并保持迄今为止最大的。

对于N个矩形,这个过程可以进行O(N^5)次操作,所以它只适用于非常小的N。


您可以通过将每个横坐标、纵坐标替换为其索引并在位图中表示矩形来加快该过程。您在此位图中绘制每个缩小的矩形。

然后当你想测试一个候选矩形时,试试右边最长的空像素;然后尝试下一行并找到不比前一行长的最长空像素;等等到位图的底部(这可以确保您尝试所有可能的矩形)。每次尝试矩形时,检索原始坐标并计算真实面积。

下面是原始矩形,然后是压缩的位图表示和从标记的像素开始尝试的像素(尝试了四个矩形)。

【讨论】:

  • 当你说横坐标和纵坐标外界时,你是什么意思?还有你用“横坐标”表示什么?
  • @CarsonP:试着理解我的数字。
  • 横坐标是 x 坐标……哎呀! google.com/…
【解决方案3】:

这是我的方法:

  1. 我划分为子矩形。每个子矩形都是对象。子矩形声明为 2D 数组,如图所示。 https://i.stack.imgur.com/SHsJ1.png

    想要这样做,我使用 2 个排序数组而不重复元素:

    • (x_left_top 和 x_right_top)
    • (y_left_top 和 y_left_bottom)
    class Rectangle {
       constructor(left, top, width, height, area) {
                this.left = left;
                this.top = top;
                this.width = width;
                this.height = height;
                this.area = area;
       }
    }
    
  2. 所以现在我们有了子矩形数组。我们需要为我们的矩形设置区域。占用矩形将设置为 -1。

    我们可以通过这个函数检查矩形是否被占用

    //rects is array of the colorful rectangle
    //rect1 is every rectangle in picture above.
    function isOverlap(rect1, rects){
        for (let i = 0; i < rects.length; i++) {
            if (rects[i].left <= rect1.left && 
                rect1.left < rects[i].left + rects[i].width &&
                rects[i].top <= rect1.top &&
                rect1.top < rects[i].top + rects[i].height)
            {
                return true;
            } 
        }
        return false;
    }
    
  3. 现在我们有了带有矩形的二维数组,并且我们知道它们的面积。如果矩形不被占用,矩形区域将具有值 height*width 否则矩形将设置区域为-1。

  4. 现在我们有一个问题# Maximum sum rectangle in a 2D matrix 您可以在geeksforgeeks

    中查看解决方案

【讨论】:

    猜你喜欢
    • 2015-02-08
    • 1970-01-01
    • 2013-03-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-11-25
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多