Advertisement
Guest User

Closest points

a guest
Nov 12th, 2019
86
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 5.60 KB | None | 0 0
  1. #include <iostream>
  2. #include <vector>
  3. #include <cmath>
  4. #include <algorithm>
  5. #include <tuple>
  6. #include <limits>
  7. #include <iomanip>
  8.  
  9. struct point {
  10.     float x, y;
  11.     int init_num;
  12. };
  13.  
  14. bool compare_of_pair(int x_1, int y_1, int x_2, int y_2) {
  15.     if (x_1 < x_2)
  16.         return true;
  17.     else if ((y_1 < y_2) && (x_1 == x_2))
  18.         return true;
  19.     return false;
  20. }
  21.  
  22. float distance(point p_1, point p_2) {
  23.     return std::sqrt(std::pow(p_1.x - p_2.x, 2) + std::pow(p_1.y - p_2.y, 2));      
  24. }
  25.  
  26. std::tuple<float, int, int> brute_force(std::vector<point> points) {
  27.     float min = std::numeric_limits<float>::max();
  28.     int p_1 = std::numeric_limits<int>::max(), p_2 = std::numeric_limits<int>::max();
  29.     for (int i = 0; i < points.size(); i++) {
  30.         for (int j = i + 1; j < points.size(); j++) {
  31.             int min_num = std::min(points[i].init_num, points[j].init_num);
  32.             int max_num = std::max(points[i].init_num, points[j].init_num);
  33.             if (distance(points[i], points[j]) < min) {
  34.                 min = distance(points[i], points[j]);
  35.                 p_1 = min_num;
  36.                 p_2 = max_num;            }
  37.             else if ((distance(points[i], points[j]) == min) &&
  38.                     (compare_of_pair(min_num, max_num, p_1, p_2))) {
  39.                 p_1 = min_num;
  40.                 p_2 = max_num;
  41.             }
  42.         }
  43.     }
  44.     return std::make_tuple(min, p_1, p_2);
  45. }
  46.  
  47. bool x_comparer(point p_1, point p_2) {
  48.     if (p_1.x < p_2.x)
  49.         return true;
  50.     return false;
  51. }
  52.  
  53. bool y_comparer(point p_1, point p_2) {
  54.     if (p_1.y < p_2.y)
  55.         return true;
  56.     return false;
  57. }
  58.  
  59. std::tuple<float, int, int> strip_closest(std::vector<point> strip, float dist) {
  60.     float min = dist;
  61.     int p_1 = std::numeric_limits<int>::max(), p_2 = std::numeric_limits<int>::max();
  62.     std::sort(strip.begin(), strip.end(), y_comparer);
  63.     for (int i = 0; i < strip.size(); i++) {
  64.         for (int j = i + 1; j < strip.size() && (strip[j].y - strip[i].y) <= min; j++) {
  65.             int min_num = std::min(strip[i].init_num, strip[j].init_num);
  66.             int max_num = std::max(strip[i].init_num, strip[j].init_num);
  67.             if (distance(strip[i], strip[j]) < min) {
  68.                 min = distance(strip[i], strip[j]);
  69.                 p_1 = min_num;
  70.                 p_2 = max_num;
  71.             }
  72.             else if ((distance(strip[i], strip[j]) == min) &&
  73.                     (compare_of_pair(min_num, max_num, p_1, p_2))) {
  74.                 p_1 = min_num;
  75.                 p_2 = max_num;
  76.             }
  77.         }
  78.     }
  79.     return std::make_tuple(min, p_1, p_2);
  80. }
  81.  
  82.  
  83. std::tuple<float, int, int> closest_points(std::vector<point> points) {
  84.     if (points.size() <= 3)
  85.         return brute_force(points);
  86.     int mid = points.size() / 2;
  87.     int p_1, p_2;
  88.     point mid_point = points[mid];
  89.     std::vector<point> dl_vec(points.begin(), points.begin() + mid);
  90.     std::vector<point> dr_vec(points.begin() + mid, points.end());
  91.     std::tuple<float, int, int> dl = closest_points(dl_vec);
  92.     std::tuple<float, int, int> dr = closest_points(dr_vec);
  93.     float dist;
  94.     int min_num_dl = std::min(std::get<1>(dl), std::get<2>(dl));
  95.     int max_num_dl = std::max(std::get<1>(dl), std::get<2>(dl));
  96.     int min_num_dr = std::min(std::get<1>(dr), std::get<2>(dr));
  97.     int max_num_dr = std::max(std::get<1>(dr), std::get<2>(dr));
  98.     if (std::get<0>(dr) < std::get<0>(dl)) {
  99.         dist = std::get<0>(dr);
  100.         p_1 = min_num_dr;
  101.         p_2 = max_num_dr;
  102.     }
  103.     else if (std::get<0>(dr) > std::get<0>(dl)) {
  104.         dist = std::get<0>(dl);
  105.         p_1 = min_num_dl;
  106.         p_2 = max_num_dl;
  107.     }
  108.     if (std::get<0>(dr) == std::get<0>(dl)) {
  109.         if (compare_of_pair(min_num_dr, max_num_dr, min_num_dl, max_num_dl)) {
  110.             dist = std::get<0>(dr);
  111.             p_1 = min_num_dr;
  112.             p_2 = max_num_dr;
  113.         }
  114.         else {
  115.             dist = std::get<0>(dl);
  116.             p_1 = min_num_dl;
  117.             p_2 = max_num_dl;
  118.         }
  119.     }
  120.     std::vector<point> strip;
  121.     for (int i = 0; i < points.size(); i++)
  122.         if (std::abs(points[i].x - mid_point.x) <= dist)
  123.             strip.push_back(points[i]);
  124.     std::tuple<float, int, int> strip_closest_res = strip_closest(strip, dist);
  125.     bool res_of_comp = compare_of_pair(std::get<1>(strip_closest_res), std::get<2>(strip_closest_res), p_1, p_2);
  126.     if (std::get<0>(strip_closest_res) < dist) {
  127.         dist = std::get<0>(strip_closest_res);
  128.         p_1 = std::min(std::get<1>(strip_closest_res), std::get<2>(strip_closest_res));
  129.         p_2 = std::max(std::get<1>(strip_closest_res), std::get<2>(strip_closest_res));
  130.     }
  131.     else if ((std::get<0>(strip_closest_res) == dist) && (res_of_comp)) {
  132.         p_1 = std::min(std::get<1>(strip_closest_res), std::get<2>(strip_closest_res));
  133.         p_2 = std::max(std::get<1>(strip_closest_res), std::get<2>(strip_closest_res));
  134.     }
  135.     return std::make_tuple(dist, p_1, p_2);
  136. }
  137.  
  138.  
  139. int main() {
  140.     int N;
  141.     double input_1, input_2;
  142.     std::vector<point> points;
  143.     std::cin >> N;
  144.     for (int i = 0; i < N; i++) {
  145.         std::cin >> input_1 >> input_2;
  146.         point my_point;
  147.         my_point.x = input_1;
  148.         my_point.y = input_2;
  149.         my_point.init_num = i;
  150.         points.push_back(my_point);
  151.     }
  152.     std::sort(points.begin(), points.end(), x_comparer);
  153.     std::tuple<float, int, int> result = closest_points(points);
  154.     std::cout << std::fixed << std::setprecision(5) << std::get<0>(result) << ' '
  155.             << std::get<1>(result) + 1 << ' ' << std::get<2>(result) + 1 << '\n';
  156.     return 0;
  157. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement