Подтвердить что ты не робот

Треугольное разбиение

Это было проблемой на конкурсе Pacific ACM-ICPC в 2010 году. Суть его заключается в том, чтобы найти способ разбивать множество точек внутри треугольника на три подтреугольника, так что каждый раздел содержит ровно треть точек.

Ввод:

  • Координаты ограничивающего треугольника: (v1x,v1y),(v2x,v2y),(v3x,v3y)
  • Число 3n < 30000, представляющее число точек, лежащих внутри треугольника
  • Координаты точек 3n: (x_i,y_i) для i=1...3n

Вывод:

  • Точка (sx,sy), которая разбивает треугольник на 3 подтреугольника, так что каждый поддиапазон содержит ровно n точек.

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

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

Вот пример проблемы для n=2 (6 баллов). Нам даны координаты каждой из цветных точек и координат каждой вершины большого треугольника. Точка разделения окружена серым цветом.

enter image description here

Может ли кто-нибудь предложить алгоритм быстрее, чем O(n^2)?

4b9b3361

Ответ 1

Вот алгоритм O(n log n). Пусть не имеет вырождения.

Идея высокого уровня, учитывая треугольник PQR,

   P
  C \
 /  S\
R-----Q

мы первоначально размещаем центральную точку C при P. Сдвиньте C в направлении R, пока в треугольнике CPQ не будет n, а один (S) на сегменте CQ. Сдвиньте C в направлении Q до тех пор, пока треугольник CRP не будет более дефицитным (perturb C и мы закончили), или CP достигнет точки. В последнем случае сдвиньте C в сторону от P до тех пор, пока треугольник CRP уже не будет неполным (мы закончили), или CQ достигнет точки, и в этом случае мы начнем скольжение C в сторону Q снова.

Очевидно, что реализация не может "скользить", поэтому для каждого треугольника с участием C для каждой вершины S этого треугольника, отличного от C, храните точки внутри треугольника в дереве двоичного поиска, отсортированном по углу с S. Этих структур достаточно для реализации этого кинетического алгоритма.

Я не утверждаю, что этот алгоритм верен.

Что касается времени выполнения, каждое событие является пересечением точечной линии и может быть обработано во времени O(log n). Углы PC и QC и RC являются монотонными, поэтому каждая из строк O(1) попадает в каждую точку не более одного раза.

Ответ 2

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

enter image description here

  • Сортировка точек в зависимости от направления от вершины A. Сортируйте их для B и C тоже.
  • Установить текущий диапазон для вершины A для всех точек.
  • Выберите 2 средних точки из диапазона для вершины A. Эти 2 точки определяют поддиапазон для "A". Возьмите некоторую строку AD, лежащую между этими точками.
  • Итерацию для всех точек, лежащих между B и AD (начиная с BA). Остановитесь, когда найдено n точек. Выберите подменю направлений от B до точек n, а затем после n (если после n нет точки, используйте BC). Если найдено менее чем n точек, установите текущий диапазон для вершины A как левую половину текущего диапазона и перейдите к шагу 3.
  • То же, что и на шаге 4, но для вершины C.
  • Если поддиапазоны A, B, C пересекаются, выберите любую точку оттуда и закончите. В противном случае, если A&B ближе к A, установите текущий диапазон для вершины A как правую половину текущего диапазона и перейдите к шагу 3. В противном случае установите текущий диапазон для вершины A как левую половину от текущего диапазона и перейдите к шагу 3.

Сложность: сортировка O(n * log n), поиск O(n * log n). (Комбинация бинарного и линейного поиска).

Ответ 3

Вот подход, который принимает O (log n) проходы из стоимости n каждый.

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

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

Когда вы перемещаете центральную точку, вы можете выбрать, будут ли точки перемещаться в нашем из самого несбалансированного субтриангаля, но вы не можете выбрать, к какому из двух других подтреугольников они идут, или из - но вы можете предсказать, что легко от на какой стороне линии, по которой вы перемещаете центральную точку, в которой они живут, поэтому вы можете перемещать центральную точку вдоль этой линии, чтобы получить наименьшее максимальное несоответствие после переезда. В худшем случае все точки переместились в или из субтригана, который был точно сбалансирован. Однако, если небалансный субтриангл имеет n + k точек, переместив k/2 из них, вы можете в худшем случае перейти к случаю, когда он и ранее сбалансированный субтреугольник выходят на k/2. Третий поддиапазон все еще может быть неуравновешен до k, в другом направлении, но в этом случае второй проход уменьшит максимальный дисбаланс к чему-то ниже k/2.

Поэтому в случае большого дисбаланса мы можем в худшем случае уменьшить его на два прохода вышеприведенного алгоритма, поэтому в O (log n) пройдет дисбаланс, который будет достаточно мал, чтобы мы были в частных случаях где мы беспокоимся о превышении не более одной точки. Здесь я собираюсь предположить, что число таких особых случаев практически перечислимо в программе, а стоимость составляет небольшое постоянное дополнение.

Ответ 4

Я думаю, что существует алгоритм линейного времени. См. Последний абзац статьи "Освещение прожекторами - Стейгером и Стрейну". Их алгоритм работает для любых k1, k2, k3, которые суммируются до n. Поэтому k1 = k2 = k3 = n/3 является частным случаем.

Вот ссылка, в которой вы можете найти статью. http://www.sciencedirect.com/science/article/pii/S0925772197000278 ссылка CiteSeerX http://citeseerx.ist.psu.edu/viewdoc/summary?doi=10.1.1.53.4634