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

Ключевые вопросы параграфа

  • Почему перебор всех пар точек работает медленно и как этого избежать?
  • Как устроен алгоритм поиска ближайшей пары с помощью деления и сканирования полосы?
  • Как добиться точного и стабильного результата при вычислениях с вещественными числами?

Algoritmy

Задача

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

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

Решение

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

Algoritmy

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

Algoritmy

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

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

Упражнение

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

Algoritmy

Это приводит к следующему алгоритму.

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

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

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

Упражнение

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

Упражнение

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

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

Пример 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

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

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

✅ Получилось разобраться, как найти пару ближайших точек быстрее, чем за ?

👉 Оценить этот параграф

Что дальше

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

Далее — заключительный параграф главы: мы кратко подведём итоги и соберём воедино все стратегии, с которыми вы познакомились.

А пока вы не ушли дальше — закрепите материал на практике:

  • Отметьте, что урок прочитан, при помощи кнопки ниже.
  • Пройдите мини-квиз, чтобы проверить, насколько хорошо вы усвоили тему.
  • Перейдите к задачам этого параграфа и потренируйтесь.
  • Перед этим — загляните в короткий гайд о том, как работает система проверки.

Хотите обсудить, задать вопрос или не понимаете, почему код не работает? Мы всё предусмотрели — вступайте в сообщество Хендбука! Там студенты помогают друг другу разобраться.

Ключевые выводы параграфа

  • Задачу нахождения пары ближайших точек можно решить не за , а за , если использовать стратегию «Разделяй и властвуй».
  • Алгоритм включает сортировку точек по координате, рекурсивное деление множества и слияние с анализом узкой полосы шириной .
  • При слиянии достаточно проверить не все пары, а только точки в полосе, отсортированные по второй координате, — это снижает число сравнений.
  • Точная реализация требует аккуратности: важно корректно обрабатывать базовые случаи, следить за порядком точек и не упустить минимум.
Чтобы добавить в заметки выделенный текст, нажмите Ctrl + E
Предыдущий параграф9.4. Подсчёт инверсий
Следующий параграф9.6. Чему вы научились