Пусть S будет площадь сцены. Пусть A будет площадь наименьшего прямоугольника, который мы хотим нарисовать. Пусть N = S / A
Один из возможных детерминистических подходов:
Когда вы рисуете прямоугольник на пустой сцене, это делит сцену не более чем на 4 области, которые могут соответствовать вашему следующему прямоугольнику. Когда вы рисуете свой следующий прямоугольник, одна или две области делятся не более чем на 4 субрегиона (каждая), которые могут соответствовать прямоугольнику и т. Д. Вы никогда не создадите больше чем N областей, где S - это область вашей сцены, и А это площадь вашего самого маленького прямоугольника. Сохраните список регионов (несортированные - это хорошо), каждый из которых представлен своими четырьмя угловыми точками, и каждый помечен своей площадью, и используйте взвешенную по площади выборку резервуара с размером резервуара 1, чтобы выбрать область с вероятностью, пропорциональной его площади, самое большее за один проход по списку. Затем поместите прямоугольник в случайном месте в этой области. (Выберите случайную точку в нижней левой части области, которая позволяет рисовать прямоугольник с этой точкой в качестве ее нижнего левого угла, не ударяя по верхней или правой стене.)
Если вы не начинаете с пустого этапа, просто создайте список доступных областей в O (N) (например, перерисовав все существующие прямоугольники на пустом этапе в любом порядке), прежде чем искать свой первый указать, чтобы нарисовать новый прямоугольник.
Примечание. Вы можете изменить размер резервуара на k, чтобы выбрать следующие k прямоугольников за один шаг.
Примечание 2. В качестве альтернативы можно сохранить доступные области в дереве, где вес каждого ребра равен сумме областей областей в поддереве над областью этапа. Затем, чтобы выбрать область в O (logN), мы рекурсивно выбираем корень с вероятностной областью корневой области / S или каждое поддерево с вероятностным весом края / S. Однако обновление весов при повторной балансировке дерева будет раздражать.
Один из возможных рандомизированных подходов:
Выберите случайную точку на сцене. Если вы можете нарисовать один или несколько прямоугольников, которые содержат точку (а не только тот, у которого точка находится в левом нижнем углу), то верните случайно расположенный прямоугольник, содержащий эту точку. Можно расположить прямоугольник без смещения с некоторыми тонкостями, но я оставлю это вам.
В худшем случае есть один пробел, достаточно большой для нашего прямоугольника, а остальная часть сцены заполнена. Таким образом, этот подход успешен с вероятностью> 1 / N или не с вероятностью <1-1 / N. Повторите N раз. Теперь мы терпим неудачу с вероятностью <(1-1 / N) ^ N <1 / e. Под неудачей мы подразумеваем, что есть место для нашего прямоугольника, но мы не нашли его. Под успехом мы подразумеваем, что нашли пространство, если оно существует. Чтобы достичь разумной вероятности успеха, мы повторяем либо Nlog (N) раз для вероятности отказа 1 / N, либо N² раз для вероятности отказа 1 / e ^ N. </p>
Резюме: Попробуйте случайные точки, пока мы не найдем пробел, останавливаясь после попыток NlogN (или N²), и в этом случае мы можем быть уверены, что пробела не существует.