Решение задачи о паре ближайших точек
Построение алгоритма по общей схеме алгоритмов "разделяй-и-властвуй". Проведение поиска треугольника с минимальным периметром. Перебор всех пар и вычисление расстояния для каждой. Ввод структуры данных для хранения точки. Слияние двух множеств точек.
Рубрика | Программирование, компьютеры и кибернетика |
Вид | курсовая работа |
Язык | русский |
Дата добавления | 29.11.2012 |
Размер файла | 107,0 K |
Отправить свою хорошую работу в базу знаний просто. Используйте форму, расположенную ниже
Студенты, аспиранты, молодые ученые, использующие базу знаний в своей учебе и работе, будут вам очень благодарны.
Размещено на http://www.allbest.ru/
Размещено на http://www.allbest.ru/
Тульский Государственный университет
Механико-Математический факультет
Кафедра «Прикладной математики и информатики»
КУРСОВАЯ РАБОТА
По дисциплине «Алгоритмические языки»
На тему «Решение задачи о паре ближайших точек»
Выполнил:
Волков Григорий Владимирович
Проверил:
Московская Юлия Валерьевна
Тула 2012
Постановка задачи
Даны точек на плоскости, заданные своими координатами . Требуется найти среди них такие две точки, расстояние между которыми минимально:
Расстояния мы берём обычные евклидовы:
Тривиальный алгоритм -- перебор всех пар и вычисление расстояния для каждой -- работает за . Ниже описывается алгоритм, работающий за время . Этот алгоритм был предложен Препаратой (Preparata) в 1975 г. Препарата и Шамос также показали, что в модели дерева решений этот алгоритм асимптотически оптимален.
Алгоритм
Построим алгоритм по общей схеме алгоритмов "разделяй-и-властвуй": алгоритм оформляем в виде рекурсивной функции, которой передаётся множество точек; эта рекурсивная функция разбивает это множество пополам, вызывает себя рекурсивно от каждой половины, а затем выполняет какие-то операции по объединению ответов. Операция объединения заключается в обнаружении случаев, когда одна точка оптимального решения попала в одну половину, а другая точка -- в другую (в этом случае рекурсивные вызовы от каждой из половинок отдельно обнаружить эту пару, конечно, не смогут). Основная сложность, как всегда, заключается в эффективной реализации этой стадии объединения. Если рекурсивной функции передаётся множество из точек, то стадия объединения должна работать не более, чем , тогда асимптотика всего алгоритма будет находиться из уравнения:
Решением этого уравнения, как известно, является .
Итак, перейдём к построению алгоритма. Чтобы в будущем прийти к эффективной реализации стадии объединения, разбивать множество точек на два будем согласно их -координатам: фактически мы проводим некоторую вертикальную прямую, разбивающую множество точек на два подмножества примерно одинаковых размеров. Такое разбиение удобно произвести следующим образом: отсортируем точки стандартно как пары чисел, т.е.:
Тогда возьмём среднюю после сортировки точку (), и все точки до неё и саму отнесём к первой половине, а все точки после неё -- ко второй половине:
Теперь, вызвавшись рекурсивно от каждого из множеств и , мы найдём ответы и для каждой из половинок. Возьмём лучший из них: .
Теперь нам надо произвести стадию объединения, т.е. попытаться обнаружить такие пары точек, расстояние между которыми меньше , причём одна точка лежит в , а другая -- в . Очевидно, что для этого достаточно рассматривать только те точки, которые отстоят от вертикальной прямой раздела не расстояние, меньшее , т.е. множество рассматриваемых на этой стадии точек равно:
Для каждой точки из множества надо попытаться найти точки, находящиеся к ней ближе, чем . Например, достаточно рассматривать только те точки, координата которых отличается не более чем на . Более того, не имеет смысла рассматривать те точки, у которых -координата больше -координаты текущей точки. Таким образом, для каждой точки определим множество рассматриваемых точек следующим образом:
Если мы отсортируем точки множества по -координате, то находить будет очень легко: это несколько точек подряд до точки .
Итак, в новых обозначениях стадия объединения выглядит следующим образом: построить множество , отсортировать в нём точки по -координате, затем для каждой точки рассмотреть все точки , и каждой пары посчитать расстояние и сравнить с текущим наилучшим расстоянием.
На первый взгляд, это по-прежнему неоптимальный алгоритм: кажется, что размеры множеств будут порядка , и требуемая асимптотика никак не получится. Однако, как это ни удивительно, можно доказать, что размер каждого из множеств есть величина , т.е. не превосходит некоторой малой константы вне зависимости от самих точек. Доказательство этого факта приведено в следующем разделе.
Наконец, обратим внимание на сортировки, которых вышеописанный алгоритм содержит сразу две: сначала сортировка по парам (,), а затем сортировка элементов множества по . На самом деле, от обеих этих сортировок внутри рекурсивной функции можно избавиться (иначе бы мы не достигли оценки для стадии объединения, и общая асимптотика алгоритма получилась бы ). От первой сортировки избавиться легко -- достаточно предварительно, до запуска рекурсии, выполнить эту сортировку: ведь внутри рекурсии сами элементы не меняются, поэтому нет никакой необходимости выполнять сортировку заново. Со второй сортировкой чуть сложнее, выполнить её предварительно не получится. Зато, вспомнивсортировку слиянием (merge sort), которая тоже работает по принципу разделяй-и-властвуй, можно просто встроить эту сортировку в нашу рекурсию. Пусть рекурсия, принимая какое-то множество точек (как мы помним, упорядоченное по парам ) возвращает это же множество, но отсортированное уже по координате . Для этого достаточно просто выполнить слияние (за ) двух результатов, возвращённых рекурсивными вызовами. Тем самым получится отсортированное по множество.
Оценка асимптотики
Чтобы показать, что вышеописанный алгоритм действительно выполняется за , нам осталось доказать следующий факт: .
Итак, пусть мы рассматриваем какую-то точку ; напомним, что множество -- это множество точек, -координата которых лежит в отрезке , а, кроме того, по координате и сама точка , и все точки множества лежат в полосе шириной . Иными словами, рассматриваемые нами точки и лежат в прямоугольнике размера .
Наша задача -- оценить максимальное количество точек, которое может лежать в этом прямоугольнике ; тем самым мы оценим и максимальный размер множества . При этом при оценке надо не забывать, что могут встречаться повторяющиеся точки.
Вспомним, что получалось как минимум из двух результатов рекурсивных вызовов -- от множеств и , причём содержит точки слева от линии раздела и частично на ней, -- оставшиеся точки линии раздела и точки справа от неё. Для любой пары точек из , равно как и из , расстояние не может оказаться меньше -- иначе бы это означало некорректность работы рекурсивной функции.
Для оценки максимального количества точек в прямоугольнике разобьём его на два квадрата , к первому квадрату отнесём все точки , а ко второму -- все остальные, т.е. . Из приведённых выше соображений следует, что в каждом из этих квадратов расстояние между любыми двумя точками не менее .
Покажем, что в каждом квадрате не более четырёх точек. Например, это можно сделать следующим образом: разобьём квадрат на 4 подквадрата со сторонами . Тогда в каждом из этих подквадратов не может быть больше одной точки (т.к. даже диагональ равна , что меньше ). Следовательно, во всём квадрате не может быть более 4 точек.
Итак, мы доказали, что в прямоугольнике не может быть больше точек, а, следовательно, размер множества не может превосходить , что и требовалось доказать.
Реализация
Введём структуру данных для хранения точки (её координаты и некий номер) и операторы сравнения, необходимые для двух видов сортировки:
struct pt {
int x, y, id;
};
inline bool cmp_x (const pt & a, const pt & b) {
return a.x < b.x || a.x == b.x && a.y < b.y;
}
inline bool cmp_y (const pt & a, const pt & b) {
return a.y < b.y;
}
pt a[MAXN];
Для удобной реализации рекурсии введём вспомогательную функцию , которая будет вычислять расстояние между двумя точками и проверять, не лучше ли это текущего ответа:
double mindist;
int ansa, ansb;
inline void upd_ans (const pt & a, const pt & b) {
double dist = sqrt ((a.x-b.x)*(a.x-b.x) + (a.y-b.y)*(a.y-b.y) + .0);
if (dist < mindist)
mindist = dist, ansa = a.id, ansb = b.id;
}
Наконец, реализация самой рекурсии. Предполагается, что перед её вызовом массив уже отсортирован по -координате. Рекурсии передаётся просто два указателя , , которые указывают, что она должна искать ответ для . Если расстояние между и слишком мало, то рекурсию надо остановить, и выполнить тривиальный алгоритм поиска ближайшей пары и затем отсортировать подмассив по -координате.
Для слияния двух множеств точек, полученных от рекурсивных вызовов, в одно (упорядоченное по -координате), мы используем стандартную функцию STL , и создаём вспомогательный буфер (один на все рекурсивные вызовы). (Использовать нецелесообразно, т.к. она в общем случае работает не за линейное время).
Наконец, множество хранится в том же массиве .
void rec (int l, int r) {
if (r - l <= 3) {
for (int i=l; i<=r; ++i)
for (int j=i+1; j<=r; ++j)
upd_ans (a[i], a[j]);
sort (a+l, a+r+1, &cmp_y);
return;
}
int m = (l + r) >> 1;
int midx = a[m].x;
rec (l, m), rec (m+1, r);
static pt t[MAXN];
merge (a+l, a+m+1, a+m+1, a+r+1, t, &cmp_y);
copy (t, t+r-l+1, a+l);
int tsz = 0;
for (int i=l; i<=r; ++i)
if (abs (a[i].x - midx) < mindist) {
for (int j=tsz-1; j>=0 && a[i].y - t[j].y < mindist; --j)
upd_ans (a[i], t[j]);
t[tsz++] = a[i];
}
}
Кстати говоря, если все координаты целые, то на время работы рекурсии можно вообще не переходить к дробным величинам, и хранить в квадрат минимального расстояния.
В основной программе вызывать рекурсию следует так:
sort (a, a+n, &cmp_x);
mindist = 1E20;
rec (0, n-1);
Обобщение: поиск треугольника с минимальным периметром
алгоритм ввод структура множество
Описанный выше алгоритм интересно обобщается и на эту задачу: среди заданного множества точек выбрать три различных точки так, чтобы сумма попарных расстояний между ними была наименьшей.
По сути, для решения этой задачи алгоритм остаётся прежним: мы разделяем поле на две половинки вертикальной прямой, вызываем решение рекурсивно от обеих половинок, выбираем минимум из найденных периметров, строим полоску толщиной , и в ней перебираем все треугольники, способные улучшить ответ. (Отметим, что у треугольника с периметром длиннейшая сторона .)
Размещено на Allbest.ru
...Подобные документы
Основная цель этого блока, ввод данных для работы программы. Дополнительная цель, вывод информации. Два условия проверки вводимых данных. Первое условие проверки на количество точек. Второе, на правильность ввода координат точек. Созданные подпрограммы.
лабораторная работа [154,3 K], добавлен 13.02.2009Решение задач по информатике, перебор различных комбинаторных конфигураций объектов и выбор наилучшего, с точки зрения условия задачи. Генерация k-элементных подмножеств, всех подмножеств данного множества, всех перестановок n-элементного множества.
реферат [44,0 K], добавлен 03.01.2010Определение уравнения одной и двух прямых на плоскости. Составление рекурсивного алгоритма построения всевозможных простых замкнутых ломаных через n произвольных точек методом треугольника и его реализация с помощью языка программирования Turbo Pascal.
курсовая работа [475,9 K], добавлен 25.02.2010Разработка ввода с клавиатуры и вывода на экран монитора данных с помощью стандартных функций printf и scanf. Ввод количества материальных точек. Работа с линейным списком. Хранение содержимого списка в блоке ячеек памяти с последовательными адресами.
курсовая работа [176,8 K], добавлен 18.01.2016Постановка задачи нелинейного программирования. Определение стационарных точек и их типа. Построение линий уровней, трехмерного графика целевой функции и ограничения. Графическое и аналитическое решение задачи. Руководство пользователя и схема алгоритма.
курсовая работа [2,5 M], добавлен 17.12.2012Постановка задачи и ее математическая модель. Блок-схема алгоритма обработки массивов координат точек. Тестирование алгоритма сортировки. Используемые глобальные и локальные переменные. Листинг программы на языке Си. Анализ результатов. Пример работы.
курсовая работа [1,8 M], добавлен 08.11.2012Виды алгоритмов как логико-математических средств, характеристика свойств. Корректный вывод алгоритма при решении вычислительной задачи. Механизм реализации алгоритма, его описание. Решение задачи Майхилла при помощи автоматной модели поведения стрелка.
курсовая работа [53,6 K], добавлен 17.07.2014Общие требования к изображению отрезка с помощью цифрового дифференциального анализатора. Сравнительный анализ обычного и несимметричного алгоритмов и алгоритма Брезенхема для генерации векторов (соединения двух точек изображения отрезком прямой).
презентация [65,3 K], добавлен 14.08.2013Организация входных и выходных данных для задачи нахождения общей точки для всех кругов на плоскости. Словесное описание действий и операций, выполняемых программой для получения конечного результата. Выбор технических и программных средств приложения.
курсовая работа [314,1 K], добавлен 30.06.2014Основные этапы определения радиуса и центра окружности, проходящей через три различные точки заданного множества точек. Особенности построения алгоритма на языке программирования. Составление тестовых примеров для демонстрации возможностей программы.
контрольная работа [103,9 K], добавлен 21.08.2013Функциональная схема объекта заданной структуры. Выбор алгоритма диагностирования. Построение принципиальной схемы дешифратора технического объекта. Выбор элементной базы и построение принципиальной схемы устройства автоматического поиска неисправностей.
контрольная работа [196,9 K], добавлен 28.01.2017Концептуальная модель операции. Математическая постановка задачи. Описание метода ветвей и границ, прямого перебора. Проектирование сценария диалога. Описание структур данных. Ручная реализация решения задачи с помощью алгоритма Литла и перебора.
курсовая работа [202,6 K], добавлен 14.12.2013Переход от словесной неформальной постановки к математической формулировке данной задачи. Оценка различных вариантов с целью выбора наиболее эффективных структур данных и алгоритмов обработки. Реализация алгоритмов на одном из языков программирования.
курсовая работа [35,0 K], добавлен 25.06.2013Цель маршрутизации - доставка пакетов по назначению с максимизацией эффективности. Построение алгоритмов поиска кратчайшего пути маршрутизации, расчёт пути с минимальным количеством переходов. Характеристики протокола RIP и построение маршрутных таблиц.
курсовая работа [74,1 K], добавлен 26.08.2010Основные особенности эволюционных алгоритмов. Описание алгоритмов селекции, мутации, скрещивания, применяемых для реализации генетических алгоритмов. Вычисление функции приспособленности. Программная реализация. Тестирование и руководство пользователя.
курсовая работа [1,3 M], добавлен 11.03.2014Примеры построения тестов и технологии исследования алгоритмов на их основе. Построение тестов на основе метода покрытия решений и проведение исследования соответствующего исходного алгоритма и алгоритма с ошибками в операторах проверки условий.
контрольная работа [224,8 K], добавлен 24.05.2016Эскизный, технический и рабочий проект расчета основоположной задачи теории множеств, решение которой необходимо для доказывания теорем высшей математики. Разработка алгоритма и написание программы в среде Delphi 7 на языке программирования Delphi.
курсовая работа [1,5 M], добавлен 21.09.2011Методы реализации алгоритмов сортировки и алгоритмов поиска на языках программирования высокого уровня. Программирование алгоритмов сортировки и поиска в рамках создаваемого программного средства на языке Delphi. Создание руководства пользователя.
курсовая работа [1,7 M], добавлен 16.04.2012Алгоритм сортировки Шейкер: математическое описание задачи и описание алгоритма. Алгоритм покрытия: построение одного кратчайшего покрытия. Описание схемы и работы алгоритма на графах: нахождение кратчайшего пути. Контрольные примеры работы алгоритмов.
курсовая работа [43,8 K], добавлен 19.10.2010Обзор алгоритмов распознания объектов на двумерных изображениях. Выбор языка программирования. Обнаружение устойчивых признаков изображения. Исследование алгоритмов поиска объектов на плоскости. Модификация алгоритма поиска максимума дискретной функции.
дипломная работа [1,0 M], добавлен 16.06.2013