Алгоритм нахождения наименьшего количества прямоугольников для покрытия набора прямоугольников без наложения - PullRequest
66 голосов
/ 07 мая 2011

У меня есть набор прямоугольников, и я хотел бы «уменьшить» набор, чтобы у меня было наименьшее количество прямоугольников, чтобы описать ту же область, что и исходный набор. Если возможно, я бы хотел, чтобы он также был быстрым, но я больше обеспокоен тем, чтобы число прямоугольников было как можно меньше. У меня есть подход, который работает большую часть времени.

В настоящее время я начинаю с самого левого верхнего прямоугольника и смотрю, могу ли я развернуть его вправо и вниз, сохраняя при этом прямоугольник. Я делаю это до тех пор, пока он больше не может расширяться, удаляю и разделяю все пересекающиеся прямоугольники и добавляю развернутый прямоугольник обратно в список. Затем я начинаю процесс снова со следующего верхнего левого прямоугольника и так далее. Но в некоторых случаях это не работает. Например: enter image description here

При таком наборе из трех прямоугольников правильное решение будет заканчиваться двумя прямоугольниками, например так: enter image description here

Однако в этом случае мой алгоритм начинается с обработки синего прямоугольника. Это расширяется вниз и разбивает желтый прямоугольник (правильно). Но затем, когда обрабатывается остаток от желтого прямоугольника, а не расширяется вниз, он сначала расширяется вправо и возвращает часть, которая была ранее отделена. Затем обрабатывается последний прямоугольник, и он не может расширяться вправо или вниз, поэтому оставляется исходный набор прямоугольников. Я мог бы настроить алгоритм, чтобы сначала развернуть вниз, а затем вправо. Это исправит этот случай, но вызовет ту же проблему в аналогичном сценарии, который был перевернут.

Редактировать: Просто чтобы уточнить, исходный набор прямоугольников не перекрывается и не должен быть соединен. И если подмножество прямоугольников соединено, у многоугольника, который полностью покрывает их, могут быть отверстия в нем.

1 Ответ

119 голосов
/ 09 июля 2011

Несмотря на заголовок вашего вопроса, я думаю, что вы на самом деле ищете минимальное рассечение на прямоугольники прямолинейного многоугольника.(Ссылки Джейсона о минимальном покрытии прямоугольниками, что является совершенно другой проблемой.)

Дэвид Эппштейн обсуждает эту проблему в разделе 3 своей статьи 2010 года об опросе Теоретико-графические решения задач вычислительной геометрии , и он дает хорошее резюме в этот ответ на mathoverflow.net :

Идея состоит в том, чтобы найти максимумчисло непересекающихся диагональных осей, параллельных оси, которые имеют две вогнутые вершины в качестве конечных точек, разбиваются вдоль них, а затем образуют еще одно разбиение для каждой оставшейся вогнутой вершины.Чтобы найти максимальное количество непересекающихся диагональных осей, параллельных, сформируйте график пересечений диагоналей;этот граф является двудольным, поэтому его максимальное независимое множество можно найти за полиномиальное время с помощью методов сопоставления графов.

Вот мой глянец на этом замечательном кратком описании, используя рисунок 2 из статьи Эппштейна.Предположим, у нас есть прямолинейный многоугольник, возможно, с отверстиями.

Когда многоугольник рассекается на прямоугольники, каждая из вогнутых вершин должна встречаться хотя бы одним краем разреза,Таким образом, мы получаем сечение минимум , если как можно больше этих ребер выполняют двойную функцию, то есть они соединяют две вогнутые вершины.

Итак, давайте нарисуем параллельные оси диагоналимежду двумя вогнутыми вершинами, которые полностью содержатся в многоугольнике.(«Ось параллельная» здесь означает «горизонтальная или вертикальная», а диагональ многоугольника - это линия, соединяющая две несмежные вершины.) Мы хотим использовать как можно больше таких линий врассечение до тех пор, пока они не пересекаются.

(Если нет диагональных осей, рассечение является тривиальным - просто сделайте разрез из каждой вогнутой вершины. Илиесли нет пересечений между диагональными осями, то мы используем их все, плюс вырез из каждой оставшейся вогнутой вершины. В противном случае читаем дальше.)

График пересечений наборасегментов линии имеет узел для каждого сегмента линии, и ребро соединяет два узла, если линии пересекаются.Вот график пересечения для диагональных осей:

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

Найти максимальное независимое множество в общем графе - задача NP-сложная, но в частном случае двудольного графа, Теорема Кёнига показывает, что она эквивалентна проблеме поиска максимального соответствия, которая может быть решена за полиномиальное время, например, с помощью алгоритма Хопкрофта-Карпа .У данного графа может быть несколько максимальных совпадений, но подойдет любой из них, так как все они имеют одинаковый размер.В этом примере все максимальные соответствия имеют три пары вершин, например {(2, 4), (6, 3), (7, 8)}:

(Другие максимальные соответствия на этом графике включают {(1, 3), (2, 5), (7, 8)}; {(2, 4), (3, 6), (5, 7)};{(1, 3), (2, 4), (7, 8)}.)

Чтобы получить максимальное совпадение с коротвечая минимальное покрытие вершин , примените доказательство теоремы Кенига .В приведенном выше сопоставлении левый набор равен L = {1, 2, 6, 7}, правый набор равен R = {3, 4, 5, 8},и набор несопоставленных вершин в L равен U = {1}.В U есть только один чередующийся путь, а именно 1–3–6, поэтому набор вершин в чередующихся путях равен Z = {1, 3, 6} и минимальнымпокрытие вершины, таким образом, составляет K = ( L \ Z ) ∪ ( R Z ) = {2, 3, 7}, показано красным ниже, с максимальным независимым набором зеленого цвета:

Если перевести это обратно в проблему рассечения, это означает, что мы можем использовать пять осей- параллельные диагонали в расчленении:

Наконец, сделайте разрез из каждой оставшейся вогнутой вершины, чтобы завершить рассечение:

...