Форум программистов, компьютерный форум, киберфорум
С++ для начинающих
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск  
 
 
Рейтинг 4.83/18: Рейтинг темы: голосов - 18, средняя оценка - 4.83
0 / 0 / 0
Регистрация: 11.09.2021
Сообщений: 77

Разделяй и властвуй, поиск пары ближайших точек

19.10.2022, 13:32. Показов 4485. Ответов 25
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
Задание:
1. Требуется реализовать алгоритм поиска пары ближайших точек в 2-мерном пространстве (функция closest_pair). На вход функция принимает массив точек (каждая точка задается двумя вещественными координатами x и y), на выходе она должна вернуть пару ближайших (по расстоянию) точек; порядок точек в паре значения не имеет.
2. Реализовать алгоритм наивным способом: полный перебор всех возможных пар точек и выбор ближайшей пары.
3. Реализовать алгоритм с помощью метода “разделяй и властвуй” (см. описание ниже; для требующейся в алгоритме сортировки нужно использовать эффективную реализацию, например, std::sort).
4. Замерить время работы двух реализаций на массивах случайных точек разного размера (N=10, 100, 1000 и т.д.) (использовать одинаковые входные данные для каждой реализации).
Сравнить время работы двух алгоритмов, сделать выводы.


Общая схема метода “разделяй и властвуй”:
1)Разбиение задачи на подзадачи меньшего размера
2)Решение подзадач (зачастую тем же алгоритмом через рекурсию или тривиальным способом в случае вырожденной подзадачи)
3)Получение (сборка) решения всей задачи из решений подзадач

Псевдокод алгоритма поиска пары ближайших точек методом “разделяй и властвуй” (points - массив вещественных точек в 2D)
closest_pair(points):
Если число точек меньше или равно 3, решить задачу тривиальным способом (полный перебор) и вернуть результат. Иначе:
Отсортировать точки в points по x-координате.
Разбить отсортированные точки на две равные по числу точек половины - PLeft и PRight.
pl = closest_pair(PLeft), pr = closest_pair(PRight) - пары ближайших точек в левой и правой половине соответственно.
d = min(dist(pl), dist(pr)), dist - расстояние между точками в паре (стандартное расстояние между координатами в R2).
pb = closest_pair_between(PLeft, PRight, d) - пара ближайших точек между половинами PLeft и PRight.
Из pl, pr и pb выбрать пару с минимальным расстоянием и вернуть как результат.

closest_pair_between(PLeft, PRight, d):
Найти Xm - границу между PLeft и PRight по x-координате
(Xm = (PLeft.last.x + PRight.first.x)/2).
Построить PStripe - массив из тех точек из PLeft и PRight, которые отстоят по х-координате от Xm менее чем на расстояние d.
Отсортировать точки в PStripe по y-координате.
Найти пару ближайших точек в PStripe. Для этого для каждой точки в PStripe достаточно рассматривать только следующие за ней в массиве точки до тех пор, пока расстояние между ними по y-координате менее чем d. Вернуть результат.
0
Programming
Эксперт
39485 / 9562 / 3019
Регистрация: 12.04.2006
Сообщений: 41,671
Блог
19.10.2022, 13:32
Ответы с готовыми решениями:

Перевести код поиска пары ближайших точек c C++ на С#
Всем добрый день! Натолкнулся на нужный мне алгоритм http://e-maxx.ru/algo/nearest_points с реализацией на с++, а мне нужно на с# ...

Возвести число A в степень N методом разделяй и властвуй
Возвести число A в степень N методом разделяй и властвуй Math.Pow(A,N) не предлагать!

Поиск пары ближайших точек
Подскажите пожалйста, алгоритмы решения задачи о паре ближайших точек

25
0 / 0 / 0
Регистрация: 11.09.2021
Сообщений: 77
03.11.2022, 16:50  [ТС]
Студворк — интернет-сервис помощи студентам
Не помогло

Добавлено через 5 часов 16 минут
В чем проблема??? Помогите!
0
0 / 0 / 0
Регистрация: 11.09.2021
Сообщений: 77
04.11.2022, 06:07  [ТС]
SmallEvil,
Не помогло
0
 Аватар для SmallEvil
4086 / 2975 / 813
Регистрация: 29.06.2020
Сообщений: 11,000
04.11.2022, 09:56
Цитата Сообщение от Шляпадляменя Посмотреть сообщение
Не помогло
а я при чем ????
0
0 / 0 / 0
Регистрация: 11.09.2021
Сообщений: 77
04.11.2022, 11:10  [ТС]
подскажите как исправить ошибку:
вызвано исключение и открывает другую библиотеку
C++
1
2
3
4
5
6
7
8
9
#include <vector>
#include <ostream>
#include <cmath>
#include "point.h"
#include <utility>
 
// Find the closest pair of points from given points.
std::pair<Point, Point> closest_pair(const std::vector<Point>& points);
std::pair<Point, Point> closest_pair1(std::vector<Point>& points);
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
#include "point.h"
#include <utility>
#include <cmath>
using namespace std;
 
 
namespace {
    static const double EPS = 1e-8;
 
    bool equal(double a, double b) {
        return abs(a - b) < EPS;
    }
}
 
double Point::distance(const Point& p) const {
    return sqrt((x - p.x) * (x - p.x) + (y - p.y) * (y - p.y));
}
 
bool Point::operator==(const Point& p) const {
    return equal(x, p.x) && equal(y, p.y);
}
 
bool Point::operator!=(const Point& p) const {
    return !equal(x, p.x) || !equal(y, p.y);
}
 
bool Point::operator<(const Point& p) const {
    return (x < p.x) || (equal(x, p.x) && y < p.y);
}
 
bool Point::operator<=(const Point& p) const {
    return (x < p.x) || (equal(x, p.x) && ((y < p.y) || equal(y, p.y)));
}
 
ostream& operator<<(ostream& os, const Point& p) {
    os << "(" << p.x << ", " << p.y << ")";
    return os;
}
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
#include <ostream>
#include <utility>
class Point {
public:
    Point() {}
    Point(float xx, float yy) : x(xx), y(yy) {}
 
    double distance(const Point& p) const;
 
    bool operator==(const Point& p) const;
    bool operator!=(const Point& p) const;
    bool operator<(const Point& p) const;
    bool operator<=(const Point& p) const;
 
public:
    double x{ 0.0 };
    double y{ 0.0 };
};
 
std::ostream& operator<<(std::ostream& os, const Point& p);
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
#include "Header.h"
#include <stdexcept>
#include <algorithm>
#include <ctime>
#include <iostream>
#include <chrono>
#include <utility>
using namespace std;
 
bool pointxcmp(const Point& p1, const Point& p2) // Используется для сортировки точек в порядке возрастания по координате x
{
    return p1.x < p2.x;
}
bool pointycmp(const Point& p1,const Point& p2) // Используется для сортировки точек в порядке возрастания по координате y
{
    return p1.y < p2.y;
}
 
std::pair<Point, Point> closest_pair( std::vector<Point>& points) {
    int i, j;
    double mindist = INFINITY;
    float d;
    int leftindex = 0;
    int rightindex = points.size() - 1;
    if (points.size() < 2) {
        throw invalid_argument("Not enough points");
    }
    auto minimum = make_pair(points[points.size() - 2], points[points.size() - 1]);
    for (i = leftindex; i <= rightindex; i++)
        for (j = i + 1; j <= rightindex; j++)
        {
            d = points[i].distance(points[j]);
            if (d < mindist) {
                mindist = d;
 
                minimum = make_pair(points[i], points[j]);
            }
        }
    return minimum;
}
pair<Point, Point> closest_pair_between(vector<Point>& PLeft, vector<Point>& PRight, float d)
{
 
    int i;
    double Xm;
    vector<Point> PStripe;
    Xm = (PLeft[PLeft.size() - 1].x + PRight[0].x) / 2; // граница между PLeft и PRight по x - координате
    for (i = 0; i < PLeft.size(); i++) {
        if (fabs(PLeft[i].x - Xm) < d)
            PStripe.push_back(PLeft[i]);
    }
    for (i = 0; i < PRight.size(); i++) {
        if (fabs(PRight[i].x - Xm) < d)
            PStripe.push_back(PRight[i]);
    }
    sort(PStripe.begin(), PStripe.end(), pointycmp);// Сортировать по координате y от маленького к большом
    pair<Point, Point> k;
    k.first = PStripe[0];
    k.second = PStripe[1];
    double s = k.second.distance(k.first);
    double t;
    for (i = 0; i < PStripe.size(); i++)
        for (int j = i + 1; j < PStripe.size() && (PStripe[j].y - PStripe[i].y) < d; j++) {
            if ((t = PStripe[i].distance(PStripe[j])) < s) {
                s = t;
                k.first = PStripe[i];
                k.second = PStripe[j];
            }
        }
    return k;
}
 
std::pair<Point, Point> closest_pair1( std::vector<Point>& points) {
    vector<Point> b;
    int leftindex = 0;
    int rightindex = points.size() - 1;
    vector<Point> PLeft, PRight, b1;
    int i, midindex;
    double pl, pr;
    double d3 = INFINITY, d;
 
    if (points.size() <= 3) {
        return closest_pair(points);
    }
    
    else {
        std::pair<Point, Point> tmp,tmp2,pb;
 
        sort(points.begin(), points.end(), pointxcmp); // Сортировать по координате x от малого к большему
 
        midindex = (leftindex + rightindex) / 2; // Находим среднюю позицию
        for (i = 0; i <=midindex; i++) // делим набор средних точек b на две части
                PLeft.push_back(b[i]);
        for ( ;i <points.size(); i++)
                PRight.push_back(b[i]);
        tmp = closest_pair1(PLeft);
        pl =  tmp.first.distance(tmp.second);
        tmp2 = closest_pair1(PRight);
        pr = tmp2.first.distance(tmp2.second);
        d = min(pl,pr); // текущее минимальное расстояние d 
        pb = closest_pair_between(PLeft, PRight, d); // пара ближайших точек между половинами PLeft и PRight.
    }
}
 
int main() {
    vector<Point> points;
    srand(time(NULL));
    int N = 5;
    for (int i = 0; i < N; i++) {
        points.push_back(Point(rand() % 20, rand() % 20));
        cout << points[i]<<" ";
    }
    cout << endl;
    auto t1 = std::chrono::high_resolution_clock::now();
    auto minimum = closest_pair1(points);
    auto t2 = std::chrono::high_resolution_clock::now();
    auto time = std::chrono::duration<double>(t2 - t1).count();
    
    cout << minimum.first<<endl;
    cout << minimum.second;
    std::cout << "Time: " << time << " sec." << std::endl;
 }
Миниатюры
Разделяй и властвуй, поиск пары ближайших точек  
0
 Аватар для lemegeton
4903 / 2696 / 921
Регистрация: 29.11.2010
Сообщений: 5,783
04.11.2022, 11:16
Описание ошибки говорит о том, что у вас сборка не работает.
Проверяйте то, как вы собираете.

Цитата Сообщение от Шляпадляменя Посмотреть сообщение
closest_pair1({ Point(1, 1) })
Я вот вижу, что такой вызов не проканает для функции, которая принимает неконстантную ссылку на вектор point'ов. Даже если вы сборку пофиксите.
0
Вездепух
Эксперт CЭксперт С++
 Аватар для TheCalligrapher
13210 / 6843 / 1824
Регистрация: 18.10.2014
Сообщений: 17,306
04.11.2022, 11:28
Цитата Сообщение от Шляпадляменя Посмотреть сообщение
вызвано исключение и открывает другую библиотеку
Ну так тут же все очевидно

C++
1
2
3
4
5
6
    vector<Point> b;
    ...
        for (i = 0; i <=midindex; i++) // делим набор средних точек b на две части
                PLeft.push_back(b[i]);
        for ( ;i <points.size(); i++)
                PRight.push_back(b[i]);
Вектор b как был пуст изначально, так и остался пуст. А вы в него лезете по индексу i. Все падает. Что это все значит? Откуда должен был взяться некий "набор средних точек" в векторе b? В коде никто в него никакого "набора средних точек" не кладет.

Более того, возникает подозрение, что работать планировалось с массивом points. А вместо него вы почему-то лезете в какой-то пустой и никому не нужный b...

Также здесь:

Цитата Сообщение от Шляпадляменя Посмотреть сообщение
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
    vector<Point> PStripe;
    Xm = (PLeft[PLeft.size() - 1].x + PRight[0].x) / 2; // граница между PLeft и PRight по x - координате
    for (i = 0; i < PLeft.size(); i++) {
        if (fabs(PLeft[i].x - Xm) < d)
            PStripe.push_back(PLeft[i]);
    }
    for (i = 0; i < PRight.size(); i++) {
        if (fabs(PRight[i].x - Xm) < d)
            PStripe.push_back(PRight[i]);
    }
    sort(PStripe.begin(), PStripe.end(), pointycmp);// Сортировать по координате y от маленького к большом
    pair<Point, Point> k;
    k.first = PStripe[0];
    k.second = PStripe[1];
А где гарантия, что в массиве PStripe будут элементы [0] и [1]? Почему вы решили, что циклы выше гарантированно найдут как минимум две точки?
1
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
inter-admin
Эксперт
29715 / 6470 / 2152
Регистрация: 06.03.2009
Сообщений: 28,500
Блог
04.11.2022, 11:28

Поиск максимального элемента в массиве методом "разделяй и властвуй"
Я в недоумении, поиск максимального элемента в массиве сводится к цикличной проверке всех его элементов на предмет превышения значения...

Алгоритм поиска пары ближайших точек
В алгоритме есть шаг что то типа: рекурсивно найти наименьшее расстояние между точек в каждой из половин. Что значит рекурсивно? Правильно...

Разделяй и властвуй
Всем добрый вечер. Требуется написать рекурсивную функцию (методом разделяй и властвуй), вычисляющую СУММУ элементов массива (со свойством...

Метод «разделяй и властвуй»
Задачка Python3: Метод «разделяй и властвуй» Требуется определить одномерный целочисленный массив a из n элементов (например, n=30),...

Реализовать алгоритмы для задачи о поиске пары ближайших точек
Реализовать алгоритмы для задачи о поиске пары ближайших точек: 1) прямой перебор (метод грубой силы), 2) метод декомпозиции Сравнить...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
26
Ответ Создать тему
Новые блоги и статьи
Сезонность и суточность закисления почв
anaschu 04.07.2026
200 часов это все равно моловато. Есть ситуации, но нестандартные, когда смена происходит за 5 лет. Но обычно это 50 лет и более. Наверное, закисление почвы происходит сезонно в средней. . .
В чем ценность человеческого опыта в глобальном смысле?
kumehtar 03.07.2026
Возможно, ценность человека не в том, что он однажды достигает мудрости, а в том, что он становится носителем карты пути. Он знает не только истину, но и последовательность внутренних изменений,. . .
интеграция AnyLogic с самописным REST API и переход на Odoo
anaschu 03.07.2026
Успешная интеграция AnyLogic с самописным REST API и переход на промышленную Odoo WMS Сегодня проделал огромный путь от простой симуляции физических процессов до построения полноценной. . .
Поиск всех путей на ориентированном графе. Linux
dcc0 02.07.2026
Переработка старого кода из моей статьи. Через несколько переработок от PHP кода к C89 (надеюсь, 89). Но довольно запутанно получилось. Код для Linux. Но если убрать time и то, что с ним. . .
Сам себя обучал rest api
anaschu 02.07.2026
Педагогический лайфхак: Почему чистый REST API для ученика намного круче, чем готовые библиотеки Когда мы отказались от капризного JAR-файла AnyLogic и переписали код на стандартный HttpClient,. . .
rest api anylogic - выполнение модели на своём русском сайте
anaschu 02.07.2026
Как подружиться с AnyLogic Cloud API, победить провайдеров и развернуться Java-бэкенд в Docker на бесплатном хостинге: Двухдневный лог борьбы Всем привет! Хочу поделиться свежим (и довольно. . .
Где деньги лежат
kumehtar 02.07.2026
Это - японская подводная лодка I-52 (тип C2, кодовое имя Momi) вышла из Японии в марте 1944 года с миссией в оккупированную немцами Францию (Лорьян). Это была одна из «Янаги»-миссий по обмену. . .
Krabik для WoW 3.3.5a, многоязычный
AmbA 02.07.2026
Допилил бота, думаю что окончательно. Изменения: - добавлена многоязычность - добавлено снятие скриншотов - добавлено поддержание бафов хождения по воде (для жреца, дк и шамана) - и так, по. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru