什么是在最大可能矩形块中返回空闲空间的算法?

时间:2009-12-07 12:36:27

标签: algorithm layout

算法

考虑这种布局:

+-------------+
|             |
|             |
|   +--+      |
|   |##|      |
|   |##|      |
|   +--+------+
|      |######|
|      |######|
+------+------+

黑色部分是占用空间。现在我需要一个返回最大剩余矩形空间的算法。 (从上到下,从左到右排序。)

像这样:

1                 2          3            4
+-------------+   +----      -------+
|#############|   |###        ######|
|#############|   |###        ######|
|   +--+      |   |###+      +######|
                  |###|      |######|
                  |###|      |######|
                  |###+      +------|     |   +--+
                  |###                    |######|
                  |###                    |######|
                  +----                   +------+

输入

封闭容器的宽度和高度。 (我的代码中的一页。)

已占用矩形的列表。它们可以是您喜欢的任何形式。 E.g。 (x,y,宽度,高度)或(x1,y1,x2,y2)

我正在处理花车,因此首选数学解决方案。

8 个答案:

答案 0 :(得分:6)

从您的示例中可以看出,您并不是要求排除重叠(例如,1和2有左上角的分段),所以这可能符合您的需求:

  1. 根据占用空间所标识的角落将空间划分为矩形。

  2. 通过将线段从这些角延伸到整个空间的边缘来形成“基本矩形”。

  3. 使用任何系统的订单(例如从上到下,从左到右):

    3.1。选择一个基本矩形,并尽可能将其扩展到具有共同边的其他基本矩形。

    3.2。形成所有(唯一的)这种扩展矩形的集合。

  4. 请注意,这会根据步骤2中的“基本矩形”进行搜索/构建,而不是逐点遍历整个空间,因此性能应该更好。

答案 1 :(得分:1)

请原谅我写代码:

for(int y = 0; y < rows; y++){

  for(int x = 0; x < columns; x++){
     // (x, y) would be the current space

     if(checkEmptySpace(x,y)){
       // empty space found

     }

  }

}

这是最简单直接的方法。但不好的一点是,它必须遍历可能导致效率低下的所有空间。

简易:

  1. STEP1 )在行为空时遍历所有行
  2. STEP1 )在行中找到占用空间时停止
    1. STEP1 )仅在第一次将当前行的值存储到TOP_EMPTY
  3. STEP2 )如果剩余的行数是&gt;列数转到第8步
  4. STEP2 )循环显示剩余的行
  5. STEP2 )计算占用空间前的空间
  6. STEP2 )计算占用空间后面的空间
  7. STEP2 )循环结束
  8. STEP2 )转到13
  9. STEP2 )循环列
  10. STEP2 )跳过TOP_EMPTY行
  11. STEP2 )计算列
  12. 中占用空间之前的空间
  13. STEP2 )计算列
  14. 中占用空格后的空间
  15. STEP2 )循环结束
  16. STEP3 )使用TOP_EMPTY * no计算顶部的空间。列
  17. DONE。

答案 2 :(得分:1)

char mark = 'A';
for(i from 0 to rows)
    colstart = 0;
    while(colstart = next empty col in ith row)
        width = 0;
        for(j from colstart to columns)
        {
            if(empty)
                width++;
            else 
                break;
        }
        if(width == 0)
            continue
        for(n from colstart to colstart + width)
            for(m from i to rows)
                if(!empty)
                    break;
            if(m != i)
                set the rectangle from i, colstart to m - 1, colstart + width 
                with mark char and increment mark;

更新:java代码。

public class Program
{
    public static char occuppied;
    public static char vacant;
    public static char mark;
    public static void main(String[] args)
    {
        int rows = 7;
        int cols = 11;
        mark = 'A';
        occuppied = '#';
        vacant = '-';
        char[][] matrix = new char[rows][cols];
        setRect(matrix, vacant, 0, 0, rows, cols);
        setRect(matrix, occuppied, 3, 3, 2, 2);
        setRect(matrix, occuppied, 5, 5, 2, 6);

        print(matrix);
        for(int i = 0; i < rows; i++)
        {
            int colstart = 0;
            while((colstart = nextEmptyCol(matrix[i], colstart)) != -1)
            {
                int width = 0;
                for(int j = colstart; j < cols; j++)
                {
                    if(matrix[i][j] == vacant)
                        width++;
                    else
                        break;
                }
                if(width == 0)
                    continue;
                int height = 1;
                outer:
                for(; height + i < rows; height++)
                    for(int n = 0; n < width; n++)
                    {
                        if(matrix[i + height][colstart + n] == occuppied)
                            break outer;
                    }
                System.out.println("width = " + width + ", height = " + height);
                setRect(matrix, mark, i, colstart, height, width);
                print(matrix);
                mark++;
            }
        }
    }
    public static void setRect(char[][] matrix, char c, int startrow, int startcol, int numrows, int numcols)
    {
        for(int i = 0; i < numrows; i++)
            for(int j = 0; j < numcols; j++)
                matrix[startrow + i][startcol + j] = c;
    }
    public static void print(char[][] matrix)
    {
        int rows = matrix.length;
        int cols = matrix[0].length;
        for(int i = 0; i < rows; i++)
        {
            for(int j = 0; j < cols; j++)
                System.out.print(matrix[i][j] + " ");
            System.out.println();
        }
        for(int i = 0; i < cols; i++)
            System.out.print("==");
        System.out.println();
    }
    public static int nextEmptyCol(char[] row, int start)
    {
        for(int i = start; i < row.length; i++)
            if(row[i] == vacant)
                return i;
        return -1;
    }
}

答案 3 :(得分:0)

  1. 开始
  2. 设置行= 0,列= 0
  3. 如果是可用空间:
    1. 从水平方向开始获取最大的自由矩形
  4. 如果没有,并且在最后一列,而不是在结尾,行+ 1,列= 0和转到3
  5. 如果不是在最后一列,则为+列,并为goto 3
  6. else end
  7. (注意3.1是相同的算法,只有倒置的自由/阻塞,并且坐标不同)

答案 4 :(得分:0)

您正在寻找与Code Golf: Running Water

类似的内容

答案 5 :(得分:0)

我认为只考虑对象不会得到最好的数学。

例如,在下图中,“r”rect是最佳匹配,但不会从任何角落开始。

+-------------+
|    rrrr     |
|+--+rrrr +--+|
||##|rrrr |##||
||##|rrrr |##||
||##|rrrr |##||
||##|rrrr |##||
|+--+rrrr +--+|
|    rrrr     |
+-------------+

答案 6 :(得分:0)

这是我用于完全相同情况的算法:

这将返回空空间矩形的列表。

  1. 在从左上到右下的列表中排列已知障碍物
  2. 创建第一个空白矩形,该矩形将占据您要检查的整个区域
  3. 对于每个障碍(O),依次为:
    1. 对于每个与O重叠的空白空间
      1. 删除空白矩形(ESR)
      2. 如果ESR.left < O.left,请用NESR.right = O.left创建新的空白矩形(NESR)并将其添加到ESR列表中,其他障碍物必须检查是否重叠。
      3. 如果ESR.right > O.right,则创建新的ESR,NESR.left = O.right
      4. 如果ESR.bottom < O.bottom,则创建新的ESR,NESR.top = O.bottom
      5. 如果ESR.top > O.top,则创建新的ESR,NESR.bottom = O.top

N.B::这是If序列,不是if序列。这意味着您为每个重叠部分最多创建4个新的ESR。

说明

  • 我们创建了一个巨大的“空空间矩形”,然后检查每个已知障碍物是否与障碍物重叠(因为矩形覆盖了所有内容,所以显然会重叠)。
  • 第一个障碍物会将第一个“空白空间”矩形拆分为最多4个较小的矩形。固定为不重叠。
  • 然后,第二障碍物将检查它是否与任何新创建的空白矩形重叠。重叠的每个矩形都进一步细分,最多可以划分为4个新矩形。这些都不会与障碍物1或障碍物2重叠。
  • 我们一直这样,直到检查完所有障碍。
  • 我们最终得到了一个没有任何障碍的空白区域列表。但是我们肯定会有重叠。

答案 7 :(得分:-1)

我认为您可以实施Montecarlo Approach

问候。