Да, вы можете сделать значительно лучше, чем перебор.
Под грубой силой я предполагаю, что вы имеете в виду проверку всех трех точек и выбор одной с максимальной площадью. Это выполняется за O (n 3 ) времени , но оказывается, что это можно сделать не только за O (n 2 ) но в O (n) время !
[ Обновление: В статье, опубликованной в 2017 году, на примере показано, что решение O (n) не работает для определенного класса полигонов. См. этот ответ для более подробной информации. Но алгоритм O (n 2 ) все еще корректен.]
Сначала отсортировав точки / вычислив выпуклую оболочку (за время O (n log n)), если необходимо, мы можем предположить, что имеем выпуклый многоугольник / оболочку с точками, циклически отсортированными в порядке их появления в многоугольнике. Назовите точки 1, 2, 3,…, n. Пусть (переменные) точки A, B и C начинаются с 1, 2 и 3 соответственно (в циклическом порядке). Мы будем двигаться A, B, C, пока ABC не станет треугольником максимальной площади. (Идея аналогична методу вращающихся суппортов , который используется при расчете диаметра (самая дальняя пара) .)
С фиксированными A и B, продвижение C (например, изначально, с A = 1, B = 2, C продвигается через C = 3, C = 4,…), пока увеличивается площадь треугольника, т.е. пока Площадь (A, B, C) ≤ Площадь (A, B, C + 1). Эта точка C будет той, которая максимизирует площадь (ABC) для фиксированных A и B. (Другими словами, функция Area (ABC) равна унимодально как функция от C.)
Затем продвиньтесь B (не изменяя A и C), если это увеличивает область. Если так, снова продвиньте C как выше. Затем продвиньте B снова, если это возможно, и т. Д. Это даст максимальный площадь треугольника с A в качестве одной из вершин.
(Доказанную часть легко доказать, и простое выполнение этого отдельно для каждого A даст алгоритм O (n 2 ).)
Теперь снова продвигайте A, если это улучшает область, и т. Д. (Правильность этой части более тонкая: Добкин и Снайдер дали доказательство в своей статье, но недавняя статья показывает контрпример. I еще не поняла.)
Хотя это имеет три «вложенных» цикла, обратите внимание, что B и C всегда продвигаются «вперед», и они продвигаются в большинстве не более 2n раз (аналогично A продвигается не более n раз), поэтому все это работает в O ( о) время.
Фрагмент кода в Python (перевод на C должен быть простым):
# Assume points have been sorted already, as 0...(n-1)
A = 0; B = 1; C = 2
bA= A; bB= B; bC= C #The "best" triple of points
while True: #loop A
while True: #loop B
while area(A, B, C) <= area(A, B, (C+1)%n): #loop C
C = (C+1)%n
if area(A, B, C) <= area(A, (B+1)%n, C):
B = (B+1)%n
continue
else:
break
if area(A, B, C) > area(bA, bB, bC):
bA = A; bB = B; bC = C
A = (A+1)%n
if A==B: B = (B+1)%n
if B==C: C = (C+1)%n
if A==0: break
Этот алгоритм доказан у Добкина и Снайдера, Об общем методе максимизации и минимизации среди определенных геометрических задач , FOCS 1979, и приведенный выше код является прямым переводом их Код АЛГОЛ-60. Извинения за конструкции while-if-break; должна быть возможность преобразовать их в более простые циклы while.