最近点对(分治法)

本文介绍了一个解决最近点对问题的算法实现,通过分治法找到二维平面上最近的两个点。该程序首先让用户输入点的数量及坐标,然后利用快速排序进行排序,并递归地将问题分解,最终计算出最近点对之间的距离。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

  1.  #include <iostream>
  2. #include <cmath>
  3. #include <cstdio>
  4. #include <cstdlib>
  5. #include <cstring>
  6. using namespace std;
  7. const int N = 100005;
  8. const double MAX = 10e100;
  9. const double eps = 0.00001;
  10. typedef struct TYPE
  11. {
  12.     double x, y;
  13.     int index;
  14. } Point;
  15. Point a[N], b[N], c[N];
  16. double closest(Point *, Point *, Point *, intint);
  17. double dis(Point, Point);
  18. int cmp_x(const void *, const void*);
  19. int cmp_y(const void *, const void*);
  20. int merge(Point *, Point *, intintint);
  21. inline double min(doubledouble);
  22. int main()
  23. {
  24.     int n, i;
  25.     double d;
  26. cout <<"请输入点的个数:";
  27.     cin>>n;
  28.     while (n)
  29.     {
  30.         for (i = 0; i < n; i++)
  31. {  cout <<"请输入第" <<i <<"个点坐标:";
  32. cin>>a[i].x>>a[i].y;
  33.     cout <<endl;
  34. }
  35.         qsort(a, n, sizeof(a[0]), cmp_x);
  36.         for (i = 0; i < n; i++)
  37.             a[i].index = i;
  38.         memcpy(b, a, n *sizeof(a[0]));
  39.         qsort(b, n, sizeof(b[0]), cmp_y);
  40.         d = closest(a, b, c, 0, n - 1);
  41. cout <<"最近点距为:";
  42.         cout <<d;
  43. cout <<endl <<"继续否?";
  44.         cin>>n;
  45.     }
  46.     return 0;
  47. }
  48. double closest(Point a[], Point b[], Point c[], int p, int q)
  49. {
  50.     if (q - p == 1)
  51.         return dis(a[p], a[q]);
  52.     if (q - p == 2)
  53.     {
  54.         double x1 = dis(a[p], a[q]);
  55.         double x2 = dis(a[p + 1], a[q]);
  56.         double x3 = dis(a[p], a[p + 1]);
  57.         if (x1 < x2 && x1 < x3)
  58.             return x1;
  59.         else if (x2 < x3)
  60.             return x2;
  61.         else
  62.             return x3;
  63.     }
  64.     int m = (p + q) / 2;
  65.     int i, j, k;
  66.     double d1, d2;
  67.     for (i = p, j = p, k = m + 1; i <= q; i++)
  68.         if (b[i].index <= m)
  69.             c[j++] = b[i];
  70.     //数组c左半部保存划分后左部的点, 且对y是有序的.
  71.     else
  72.         c[k++] = b[i];
  73.     d1 = closest(a, c, b, p, m);
  74.     d2 = closest(a, c, b, m + 1, q);
  75.     double dm = min(d1, d2);
  76.     merge(b, c, p, m, q); //数组c左右部分分别是对y坐标有序的, 将其合并到b.
  77.     for (i = p, k = p; i <= q; i++)
  78.         if (fabs(b[i].x - b[m].x) < dm)
  79.             c[k++] = b[i];
  80.     //找出离划分基准左右不超过dm的部分, 且仍然对y坐标有序.
  81.     for (i = p; i < k; i++)
  82.     for (j = i + 1; j < k && c[j].y - c[i].y < dm; j++)
  83.     {
  84.         double temp = dis(c[i], c[j]);
  85.         if (temp < dm)
  86.             dm = temp;
  87.     }
  88.     return dm;
  89. }
  90. double dis(Point p, Point q)  //求两个点的距离函数
  91. {
  92.     double x1 = p.x - q.x, y1 = p.y - q.y;
  93.     return sqrt(x1 *x1 + y1 * y1);
  94. }
  95. int merge(Point p[], Point q[], int s, int m, int t)
  96. {
  97.     int i, j, k;
  98.     for (i = s, j = m + 1, k = s; i <= m && j <= t;)
  99.     {
  100.         if (q[i].y > q[j].y)
  101.             p[k++] = q[j], j++;
  102.         else
  103.             p[k++] = q[i], i++;
  104.     }
  105.     while (i <= m)
  106.         p[k++] = q[i++];
  107.     while (j <= t)
  108.         p[k++] = q[j++];
  109.     memcpy(q + s, p + s, (t - s + 1) *sizeof(p[0]));
  110.     return 0;
  111. }
  112. int cmp_x(const void *p, const void *q)  //判断两点x坐标的大小关系
  113. {
  114.     double temp = ((Point*)p)->x - ((Point*)q)->x;
  115.     if (temp > 0)
  116.         return 1;
  117.     else if (fabs(temp) < eps)
  118.         return 0;
  119.     else
  120.         return  - 1;
  121. }
  122. int cmp_y(const void *p, const void *q)  ////判断两点x坐标的大小关系
  123. {
  124.     double temp = ((Point*)p)->y - ((Point*)q)->y;
  125.     if (temp > 0)
  126.         return 1;
  127.     else if (fabs(temp) < eps)
  128.         return 0;
  129.     else
  130.         return  - 1;
  131. }
  132. inline double min(double p, double q)  //返回两个double数的最小值
  133. {
  134.     return (p > q) ? (q): (p);
  135. }

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值