Что такое алгоритм возврата свободного пространства в блоках максимально возможных прямоугольников?

Алгоритм

Рассмотрим этот макет:

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

Черная часть - занимаемое пространство. Теперь мне нужен алгоритм, который возвращает наибольшие оставшиеся прямоугольные пространства. (Упорядочено сверху вниз, слева направо.)

Вот так:

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

Ввод

Ширина и высота вмещающего контейнера. (Страница в моем коде.)

Список уже занятых прямоугольников. Они могут быть в любой форме, которая вам нравится. Например. (x, y, width, height) или (x1, y1, x2, y2)

Я имею дело с поплавками, поэтому было бы предпочтительным математическое решение.

Ответ 1

Из вашего примера видно, что вы не просите исключить перекрытие (например, 1 и 2 имеют общий левый сегмент), поэтому, возможно, это будет соответствовать вашим потребностям:

  • Разделите пространство на прямоугольники на основе углов, обозначенных занятыми пространствами.

  • Формируйте "основные прямоугольники", расширяя отрезки от этих углов до краев всего пространства.

  • Используя любой систематический порядок (например, сверху вниз, слева направо):

    3,1. Выберите основной прямоугольник и увеличьте его как можно дальше с другими основными прямоугольниками, имеющими общую сторону.

    3,2. Составьте набор всех (уникальных) таких расширенных прямоугольников.

Обратите внимание, что это поиск/сборка основывается на "основных прямоугольниках" с шага 2, а не на каждом месте по всему пространству, поэтому производительность должна быть намного лучше.

Ответ 2

Извините меня за запись в кодах:

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

     }

  }

}

Это самый простой и прямой способ сделать это. но плохой момент состоит в том, что он должен пересекать все пространство, которое может вызвать неэффективность.

Самодельное:

  • (STEP1) цикл через все строки, в то время как строки пустые
  • (STEP1) останавливается, когда занятое пространство находится в строке
    • (STEP1) сохраняет значение текущей строки TOP_EMPTY только в первый раз
  • (STEP2), если число оставшихся строк - это число столбцов, перейдите к шагу 8
  • (STEP2) цикл через оставшиеся строки
  • (STEP2) вычислить пространство перед занятым пространством
  • (STEP2) вычислить пространство за занимаемым пространством
  • (STEP2) конец цикла
  • (STEP2) перейти к 13
  • (STEP2) цикл через столбцы
  • (STEP2) пропустить строки TOP_EMPTY
  • (STEP2) вычислить пространство перед занимаемым пространством в столбце
  • (STEP2) вычислить пространство после занимаемого пространства в столбце
  • (STEP2) конец цикла
  • (STEP3) вычислить пространство вверху с помощью TOP_EMPTY * no. столбцов
  • DONE.

Ответ 3

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;

update: java code.

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;
    }
}

Ответ 4

  • Начало
  • set row = 0, column = 0
  • if - свободное пространство:
    • получить наибольший свободный прямоугольник, начиная горизонтально
  • если нет, а в последнем столбце, а не в конце, строка + 1, столбец = 0 и goto 3
  • else, если не последний столбец, столбец + 1 и goto 3
  • else end

(заметим, что 3.1 - тот же алгоритм, только со свободным/заблокированным перевернутым и с разными координатами)

Ответ 6

Я думаю, что рассмотреть, что только программисты не получат лучшую математику.

Например, на изображении ниже "r" rect является наилучшим совпадением, но не начинается в любом углу.

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

Ответ 7

Я думаю, что вы можете реализовать подход Montecarlo.

С уважением.