Algoritmy

Ваша задача — найти ближайшую пару точек из заданного множества.

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

Чтобы решить эту задачу за время , разобьём с помощью правильно подобранной вертикальной линии данные точек пополам — множества и размера . Ради простоты предположим, что все координаты для данных точек различные и количество точек чётное. С помощью двух рекурсивных вызовов с параметрами и мы находим минимальные расстояния и в этих поднаборах. Пусть .

Algoritmy

Остаётся проверить, существуют ли такие точки и , при которых расстояние между ними меньше . Мы не можем себе позволить проверять все возможные такие пары, так как их . Для более быстрой проверки мы отбросим все точки из и , расстояние которых от центральной линии по больше, чем . Таким образом, мы сосредотачиваемся на следующей полосе:

Algoritmy

💡 Остановитесь и подумайте:
Почему мы можем сузиться до этой полосы?

Теперь отсортируем точки из полосы по координатам и обозначим получившийся отсортированный список . Оказывается, что если , то расстояние между точками и однозначно будет больше . Упражнение ниже это демонстрирует.

✒️ Упражнение:
Разделите полосу на квадратов, как показано ниже, и продемонстрируйте, что каждый из таких квадратов содержит максимум четыре точки ввода.

Algoritmy

Это приводит к следующему алгоритму. Сначала мы сортируем данные нам точек по их координатам , затем делим получившийся отсортированный список на две половины и размера . Находим минимальные расстояния и с помощью рекурсивных вызовов для каждого из наборов и . Пусть . Тем не менее наша работа ещё не закончена, потому что нам также нужно найти минимальное расстояние между точками из разных наборов (то есть точкой из и точкой из ) и проверить, ниже ли это расстояние, чем . Чтобы в этом убедиться, мы отфильтруем изначальный набор и оставим только точки с дистанцией по до средней линии, не превышающей . После этого мы сортируем набор точек в получившейся линии по координатам и сканируем получившийся список. Вычислим расстояние от каждой точки до семи последующих точек списка и вычислим — минимальное расстояние, которое нам встретилось во время сканирования. Затем выведем .

Время выполнения алгоритма соответствует рекуррентному соотношению.

— результат сортировки точек в полосе по координате при каждой итерации.

✒️ Упражнение:
Проанализируйте рекурсивное дерево алгоритма и докажите, что .

✒️ Упражнение:
Продемонстрируйте, как избежать сортировки при каждом рекурсивном вызове и понизить время выполнения до .

  • Формат ввода: Первая строка содержит точек. Каждая из следующих строк определяет точку .
  • Формат вывода: Минимальное расстояние.
  • Ограничения: ; — целые числа.
  • Примеры

Пример 1

Ввод

Вывод

2
0 0
3 4

5.0

Пример 2

Ввод

Вывод

11
-2 4
-2 -2
4 4
2 3
-3 -4
-4 0
-1 3
3 -1
1 1
-1 -1
-4 2

1.414213

  • Во втором примере самое маленькое расстояние — . Есть две пары точек на этом расстоянии. Ниже они выделены голубым и красным: и ; и .

Algoritmy

Помните, что расстояние между точками и равно . Так, хотя ввод и содержит только целые числа, ответ не обязательно будет целым числом, и потому вам нужно обратить внимание на точность при выводе результатов. Абсолютное значение разницы между ответом вашей программы и оптимальным значением не должно превышать . Для этого ваш ответ должен содержать не меньше четырех цифр в дробной части. Иначе даже правильно вычисленный результат может не пройти нашу систему проверки из-за ошибок при округлении.

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

Отмечайте параграфы как прочитанные чтобы видеть свой прогресс обучения

Вступайте в сообщество хендбука

Здесь можно найти единомышленников, экспертов и просто интересных собеседников. А ещё — получить помощь или поделиться знаниями.
Вступить
Сообщить об ошибке
Предыдущий параграф7.4. Подсчёт инверсий
Следующий параграф8.1. Принципы построения алгоритмов