алгоритмическая задачка
Apr. 23rd, 2008 12:17 am(будет интересно только программистам)
На работе рассказали интересную задачу. Пусть дан прямоугольный лист металла известных размеров. Из-за дефектов производства на листе есть точки, в которых металл слишком слаб - дан список таких точек, с координатами каждой. Задача: найти наибольший по площади прямоугольник внутри листа, не содержащий ни одной дефективной точки внутри себя (на границе - можно).
Искать следует только среди прямоугольников со сторонами, параллельными исходному (более общий вопрос, в котором искомый прямоугольник может быть повернут относительно всего листа, можно считать отдельной задачей - ее я вообще не знаю, как решать).
На работе рассказали интересную задачу. Пусть дан прямоугольный лист металла известных размеров. Из-за дефектов производства на листе есть точки, в которых металл слишком слаб - дан список таких точек, с координатами каждой. Задача: найти наибольший по площади прямоугольник внутри листа, не содержащий ни одной дефективной точки внутри себя (на границе - можно).
Искать следует только среди прямоугольников со сторонами, параллельными исходному (более общий вопрос, в котором искомый прямоугольник может быть повернут относительно всего листа, можно считать отдельной задачей - ее я вообще не знаю, как решать).
no subject
Date: 2008-04-22 09:36 pm (UTC)no subject
Date: 2008-04-22 09:46 pm (UTC)1. Через каждую точку проводим горизонтальную и вертикальную прямую, в результате наш лист металла оказывается разбит следующим образом:
2. Находим точки на пересечении этих прямых между собой (и прямых с краями листа, естественно):
3. Для каждой такой точки, двигаясь вправо от нее, а после - вниз, находим список прямоугольников максимальной ширины следующим образом (для примера взята точка 6, красными цифрами отмечены правые нижние углы каждого найденного прямоугольника):
4. Для полученных прямоугольников сохраняем в список координаты углов и площадь.
5. По окончанию 3-4 находим прямоугольник максимальной площади в списке.
Естественно, процесс можно слегка оптимизировать, например, прямоугольник 3 из последней иллюстрации можно не включать в список вовсе, а также не рассматривать точки на пересечении линий, которые уже находятся в списке добавленных ранее прямоугольников
no subject
Date: 2008-04-22 09:59 pm (UTC)no subject
Date: 2008-04-22 10:00 pm (UTC)(no subject)
From:no subject
Date: 2008-04-22 10:15 pm (UTC)Только надо будет учесть фактор появления непрямых углов между линиями и краями листа.
Где-то так.
no subject
Date: 2008-04-22 10:21 pm (UTC)Работает, но очень медленно :)
(no subject)
From:(no subject)
From:оффтоп
From:Re: оффтоп
From:Re: оффтоп
From:(no subject)
From:(no subject)
From:(no subject)
From:(no subject)
From:(no subject)
From:(no subject)
From:no subject
Date: 2008-04-23 09:40 am (UTC)(no subject)
From:(no subject)
From:no subject
Date: 2008-04-22 09:58 pm (UTC)no subject
Date: 2008-04-22 10:22 pm (UTC)(no subject)
From:no subject
Date: 2008-04-22 09:58 pm (UTC)1. провести через каждую точку вертикальные и горионтальные линии
2. Получаем сетку из прямоугольников, причем точно знаем что внутри любого прямоугольника дефектных точек нет
3. Теперь тупой перебор всех пар точек А и B (узлов сетки), где В всегда правее и ниже А. Проверяем входит ли дефектная точка в полученный прямоугольник, если нет, то считаем плащадь
4. Выбираем большую площадь из полученных
no subject
Date: 2008-04-22 10:20 pm (UTC)no subject
Date: 2008-04-22 10:01 pm (UTC)no subject
Date: 2008-04-22 10:22 pm (UTC)(no subject)
From:(no subject)
From:Не NP Меньше или равно N^6
From:Re: Не NP Меньше или равно N^6
From:no subject
Date: 2008-04-22 10:04 pm (UTC)2. если точки есть - последовательно сокращать размеры прямогульника (образно, или физически отрезая лишнее)
Делается так:
представить систему координат (для облегчения ориентирования)
расположить прямоугольник более длинной стороной вдоль оси X
находим 4 точки - ближайшую к верхней, левой, правой и нижней границе.
Считаем расстояние от точки до соответствующей границы
если максимальное расстояние >= (0.5*длина соответствующей стороны) то задача решена.
(т.е. если максимальное расстояние - это расстояние от точки до правого края и оно больше либо равно половине длинной стороны прямоугольника)
в противном случае через ближайшую к краю очку проводится прямая, параллельная этому краю, и пространство между проведенной прямой и краем заштриховывается
К оставшемуся прямоугольнику процедура применяется повторно, начиная с шага 1.
P.S. по крайней мере сам понял что написал :)
no subject
Date: 2008-04-27 02:46 am (UTC)no subject
Date: 2008-04-22 11:40 pm (UTC)Заранее сортируем все точки по возрастанию x. Перебираем левую границу прямоугольника (она может совпадать с левой границей листа или с x-координатой одной из точек), обозначим её x1. Для заданного x1 находим множество y-координат точек, у которых x > x1. Обозначим это множество s. Включим в s y-координаты верхней и нижней границ листа. Находим максимальную разность r среди соседних элементов в s. Обновляем максимальную площадь значением r*(правая_граница-x1). Идем по точкам в порядке уменьшения x. Для текущей точки удаляем ее y-координату из s. Обновляем r = max(r, элемент_справа_от_удаленного_y -элемент_слева_от_удаленного_y). Обновляем максимальную площадь значением r*(x-x1).
Написал запутанно, но как-то так :) Для множества s надо использовать структуру данных на основе сбалансированных деревьем, к примеру set в C++.
no subject
Date: 2008-04-23 12:13 am (UTC)(no subject)
From:(no subject)
From:no subject
Date: 2008-04-23 01:08 am (UTC)no subject
Date: 2008-04-23 01:23 am (UTC)1. Put all the dots in a quad tree O(n log n)
2. Take a sorted (by area) list of rectangles. Put the initial rectangle in - O(1).
3. Find a dot within the biggest rectangle, split that rectangle in four (with 2x overlap), and replace the original rectangle with these four O(log n).
4. Repeat 3 until no splitting dots are found. O(n) iterations (I'm not sure about that one, it may be bigger).
no subject
Date: 2008-04-23 10:19 am (UTC)We should not throw the dot after splitting the rectangle, because it may split another rectangle that becomes the biggest after the split. So, there are more than O(n) iterations, at least O(n^2).
no subject
Date: 2008-04-23 01:27 am (UTC)(Идея 1) Держим priority queue (PQ) из прямоугольников, каждому из которых присваивается вес, некоторым образом соответствующий верхней оценке максимальной площади. На каждом шаге: выгребаем из PQ прямоугольник с максимальным весом. Если в нем нет точек, задача решена, это оптимум. Если нет, выбираем точку поближе к середине, которая делит прямоугольник на две пары прямоугольников, и кладем эти четыре прямоугольника в PQ. Фокус в том, как выбрать функцию веса, которая была бы монотонной (чтобы гарантировать глобальный оптимум) и которую было бы быстро вычислять.
(Идея 2) Делим прямоугольник горизонтально, примерно пополам. Горизонтальные границы решения лежат
1) обе сверху
2) обе снизу
3) одна сверху, одна снизу.
Случаи (1) и (2) - неинтересные, они уменьшают N вдвое, то есть выгодны для нас. Рассмартивать нужно случай (3). Теперь хорошо бы разделить обе половинки, верхнюю и нижнюю, тоже надвое, и посмотреть, что получается.
Да, точки заранее нужно осортировать по горизонтали или даже положить в kd-tree.
В-общем, идея - свести задачу нахождения верхней и нижней границы к чему-то быстрому, логарифмическому.
Завтра я лечу через океан, будет время обдумать.
P.S. У меня есть смутные подозрения, что если обе идеи работают, то идея (2) даст лучшее теоретическое решение, а (1) лучше на практике :)
no subject
Date: 2008-04-27 04:25 am (UTC)Решение в духе идеи 2 подробно расписано здесь: http://portal.acm.org/citation.cfm?id=41958.41988 - сложность доказана, но уж больно геморройная сшивка в пункте 3). Я лично был стал реализовывать первую идею :)
no subject
Date: 2008-04-23 03:42 am (UTC)no subject
Date: 2008-04-23 05:41 am (UTC)no subject
Date: 2008-04-23 06:06 am (UTC)Сортируем точки по возрастанию х (х1, х2...).
Первый рассматриваемый прямоугольник - с краю, по высоте листа (Н), площадь прямоугольника = х1*Н. Дальше точка 1 делит его на два, высотой у1 и Н-у1. Точка 2 делит один из этих двух; чтобы найти какой, нужно log(2) операций, если хранить прямоугольники в упорядоченном по у списке. Проверяем площадь прямоугольника, который упирается в точку 2 (у1*х2, либо (Н-у1)*х2). Далее, для каждой точки i нужно log(i) операций для поиска разделяющегося прямоугольника, в сумме O(log(n!))=O(n*log(n)).
Далее повторяем всю процедуру, но стартуем от точки х1, а не с краю. Всё равно получается n^2*log(n).
no subject
Date: 2008-04-23 07:29 am (UTC)(no subject)
From:(no subject)
From:(no subject)
From:Жызнено
Date: 2008-04-23 09:39 am (UTC)Сразу приходит в слово Plane Sweep.
Понимаешь, что нужно отсортировать точки.
Потом нужно поддерживать структуру, которая бы содержала текущие прямоугольники. В ней нужно как-то искать и т.д.
Каждая бы точка, закрывала правым краем все текущие, била бы "напополам" тот, в который бы попала и начинала бы новый левый край.
Re: Жызнено
Date: 2008-04-23 09:57 am (UTC)Пусть H - высота большого прямоугольника.
На каждой точке следующие операции:
* Вставить прямоугольник высотой H с левым краем в точке.
* Найти прямоугольник, который разделяется точкой на два. Выбросить его с правым краем в точке и поделить его на два и тянуть дальше.
Все операции O(log n). Итого O(n log n) с начальной сортировкой.
Re: Жызнено
From:Re: Жызнено
From: (Anonymous) - Date: 2008-04-23 10:36 am (UTC) - ExpandRe: Жызнено
From:no subject
Date: 2008-04-23 10:47 am (UTC)B.Chazelle, R.Drysdale, D.Lee
Computing the largest empty rectangle, SIAM J Comp 15 (1986) 300-315
M.Orlowski
A new algorithm for largest empty rectangle problem, Algorithmica 5 (1990) 65-73
For arbitrary orientation:
A.Mukhopadkhyay, S.Rao
On computing a largest empty arbitrarily oriented rectangle, Internat. J. Comput. Geom. Appl. 13 (2003) 257--271.
no subject
Date: 2008-04-23 02:14 pm (UTC)(no subject)
From:(no subject)
From:(no subject)
From:(no subject)
From: (Anonymous) - Date: 2008-04-26 06:54 am (UTC) - Expandno subject
Date: 2008-04-23 01:39 pm (UTC)x[i], y[i] - координаты точки, имеющей порядковый номер i в списке, отсортированном по возрасатанию x.
t и b равны следующему
t[a,b] = min (y[c] : y[c]>=y[a], x[a]<=x[c]<=x[b])
b[a,b] = max (y[c] : y[c]<=y[a], x[a]<=x[c]<=x[b])
Считаются рекурсивно так за n^2
t[a,b] = (y[b-1]>y[a]) ? min(t[a,b-1],y[b-1]) : t[a,b-1]
b[a,b] = (y[b-1]<y[a]) ? max(b[a,b-1],y[b-1]) : b[a,b-1] Ответ - max( (t[a,b] - b[a,b]) * (x[b]-x[a]) )
no subject
Date: 2008-04-23 08:04 pm (UTC)(Если не хочется регистрироваться, чтобы читать условие: точки генерируются псевдослучайно внутри квадрата 1×1; гарантируется, что их не больше чем 25000.)
no subject
Date: 2008-04-23 09:22 pm (UTC)no subject
Date: 2008-04-24 07:49 am (UTC)Берём точку и перебираем листья дерева прямоугольников, проверяя принадлежность точки. Если точка лежит в пределах очередного листа, пристраиваем к нему 4 новых листа (деление этого прямоугольника вертикалью и горизонталью, проходящей через точку). Если точка лежит на границе, будет только 2 листа. Если на углу -- точка повторяется, делить нечего. Переходим к следующей точке и повторяем, пока они не кончатся.
По окончании ещё раз перебираем листья и находим самый большой.
no subject
Date: 2008-04-24 08:44 am (UTC)(no subject)
From:(no subject)
From:(no subject)
From: