Как найти треугольники с максимальной площадью?

Задача: Дано 3n точек на плоскости, причем никакие три из них не лежат на одной прямой. Построить множество n треугольников с вершинами в этих точках так, чтобы никакие два треугольника не пересекались и не содержали друг друга, а суммарная площадь этих треугольников была максимальной.
Пытаюсь найти правильный подход к задачке.
Я начал решать в лоб: сначала прохожу по всем точкам и записываю в двумерный массив все возможные треугольники.
То есть если дано 6 точек, то начало массива будет выглядеть так: [[0,1,2], [0,1,3], [0,1,4], [0,1,5], [0,2,3], [0,2,4], и т.д., где цифры в массиве - это индексы известных нам точек. Для 6 точек получается 20 разных треугольников. Для 9 точек - 84 треугольника и т.д.
Далее нужно, насколько я понимаю, сравнить каждый треугольник с каждым, чтобы выявить, какие 2 треугольника (в случае 6 точек) имеют наибольшую площадь и при этом не пересекаются. Я это реализую с помощью рекурсивной функции и получается, что для 20 треугольников будет 190 итераций (комбинаторика, сочетания из двадцати по два).
Но проблема в том, что если точек будет 9, то будет 84 возможных треугольника и уже 95284 итераций (84 по 3) и для 12 точек будет 220 треугольников и 94.966.795 итераций (220 по 4). А 15 точек программа уже вовсе не посчитает за адекватное время.
И вот проблема в том, что программа не должна крашится уже на 15-ти точках.
Я понимаю, что такой подход, по всей видимости, неправильный, но иного решения пока в голову не пришло
Не кидаю код, потому что прошу подсказать именно подход к задаче
  • Вопрос задан
  • 2060 просмотров
Решения вопроса 1
wataru
@wataru Куратор тега Алгоритмы
Разработчик на С++, экс-олимпиадник.
До 15 точек можно полным перебором сделать. Вам надо перебрать все разбиения 3n точек на тройки. Таких разбиений (3n)!/(3!)^n/n! для n=5 - это чуть больше миллиона.

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

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

Какое-то геометрическое решение в голову что-то не приходит.
Ответ написан
Комментировать
Пригласить эксперта
Ответы на вопрос 2
AgentSmith
@AgentSmith
Это мой правильный ответ на твой вопрос
Это классическая задача и старое всем известное решение - триангуляция Делоне
https://ru.wikipedia.org/wiki/%D0%A2%D1%80%D0%B8%D...
Ответ написан
@DShegolev
Ну тут явно сначала надо определить какой-то ограничивающий прямоугольник и потом рекурсивно его разбивать на более мелкие и обрабатывать его части.
Ответ написан
Комментировать
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы