coloriot

HA_62_Pairs

Aug 2nd, 2025
145
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 4.57 KB | None | 0 0
  1. #include <iostream>
  2. #include <vector>
  3. #include <algorithm>
  4. #include <cmath>
  5. #include <limits>
  6. #include <utility>
  7.  
  8. using namespace std;
  9.  
  10. struct Point {
  11.     double x, y;
  12.     int idx; // оригинальный индекс
  13. };
  14.  
  15. // Результат: два индекса и
  16. // квадрат минимального расстояния
  17. struct ClosestPairResult {
  18.     int idx1;
  19.     int idx2;
  20.     double dist2; // квадрат расстояния
  21. };
  22.  
  23. class ClosestPair {
  24. public:
  25.     // Внешний интерфейс
  26.     static ClosestPairResult findClosest(const vector<Point>& points) {
  27.         int n = points.size();
  28.         vector<Point> pts_by_x = points;
  29.         sort(pts_by_x.begin(), pts_by_x.end(), [](const Point& a, const Point& b) {
  30.             return a.x < b.x;
  31.         });
  32.         vector<Point> pts_by_y = pts_by_x; // будет переупорядочиваться в рекурсии
  33.         return recursiveSolve(pts_by_x, pts_by_y, 0, n);
  34.     }
  35.  
  36. private:
  37.     // Рекурсивное решение на диапазоне [l, r)
  38.     static ClosestPairResult recursiveSolve(vector<Point>& pts_by_x,
  39.                                             vector<Point>& pts_by_y,
  40.                                             int l, int r) {
  41.         int len = r - l;
  42.         if (len <= 1) {
  43.             return { -1, -1, numeric_limits<double>::infinity() };
  44.         }
  45.         int mid = l + len / 2;
  46.         double mid_x = pts_by_x[mid].x;
  47.  
  48.         // Разделим pts_by_y на левую и
  49.         // правую части по x, сохраняя сортировку по y
  50.         vector<Point> left_by_y;
  51.         vector<Point> right_by_y;
  52.         left_by_y.reserve(mid - l);
  53.         right_by_y.reserve(r - mid);
  54.         for (const Point& p : pts_by_y) {
  55.             if (p.x < mid_x || (p.x == mid_x && p.idx == pts_by_x[mid].idx && left_by_y.size() < (size_t)(mid - l))) {
  56.                 left_by_y.push_back(p);
  57.             } else if ((int)right_by_y.size() < (r - mid)) {
  58.                 right_by_y.push_back(p);
  59.             } else {
  60.                 left_by_y.push_back(p);
  61.             }
  62.         }
  63.  
  64.         // Левый и правый рекурсивно
  65.         ClosestPairResult left_res = recursiveSolve(pts_by_x, left_by_y, l, mid);
  66.         ClosestPairResult right_res = recursiveSolve(pts_by_x, right_by_y, mid, r);
  67.  
  68.         // Берём лучший из левого/правого
  69.         ClosestPairResult best = (left_res.dist2 < right_res.dist2) ? left_res : right_res;
  70.         double delta2 = best.dist2;
  71.         double delta = sqrt(delta2);
  72.  
  73.         // Строим полосу: точки с |x - mid_x| < delta
  74.         vector<Point> strip;
  75.         strip.reserve(r - l);
  76.         for (const Point& p : pts_by_y) {
  77.             if (fabs(p.x - mid_x) < delta) {
  78.                 strip.push_back(p);
  79.             }
  80.         }
  81.  
  82.         // Сканируем полосу: для каждой
  83.         // точки проверяем следующие до 7 по y
  84.         for (size_t i = 0; i < strip.size(); ++i) {
  85.             // Ограничиваем количество проверок
  86.             // — следующими по y достаточно проверять константу
  87.             for (size_t j = i + 1; j < strip.size() && j <= i + 7; ++j) {
  88.                 double dy = strip[j].y - strip[i].y;
  89.                 if (dy * dy >= delta2) break; // дополнительная обрезка
  90.                 double dx = strip[j].x - strip[i].x;
  91.                 double d2 = dx * dx + dy * dy;
  92.                 if (d2 < delta2) {
  93.                     delta2 = d2;
  94.                     delta = sqrt(delta2);
  95.                     best = { strip[i].idx, strip[j].idx, delta2 };
  96.                 }
  97.             }
  98.         }
  99.  
  100.         return best;
  101.     }
  102. };
  103.  
  104. int main() {
  105.     vector<Point> pts = {
  106.             {0,1,0}, {0,4,1}, {2,1,2}, {10,8,3}, {1,5,4}, {9,9,5},
  107.             {1,1,6}, {4,6,7}, {6,6,8}, {6,4,9}, {2,6,10}, {1,0,11},
  108.             {7,5,12}, {9,7,13}, {8,5,14}
  109.     };
  110.  
  111.     auto res = ClosestPair::findClosest(pts);
  112.     if (res.idx1 != -1) {
  113.         cout << "Ближайшая пара: индекс " << res.idx1 << " и " << res.idx2 << "\n";
  114.         cout << "Координаты: (" << pts[res.idx1].x << ", " << pts[res.idx1].y << ") и ("
  115.              << pts[res.idx2].x << ", " << pts[res.idx2].y << ")\n";
  116.         cout << "Минимальное расстояние: " << sqrt(res.dist2) << "\n";
  117.     } else {
  118.         cout << "Пара не найдена\n";
  119.     }
  120.     return 0;
  121. }
  122.  
  123.  
Advertisement
Add Comment
Please, Sign In to add comment