最近点问题

本文介绍了一种使用分治策略寻找平面上最近点对的算法实现,通过递归地将点集按照横坐标划分并计算左右两边及中线附近的最小距离。

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

  分治算法

      分:递归解决较小问题

      治:然后,从子问题的解构建原问题的解

我们仿照一维的情况先把所有点按照x(横坐标)从左到右升序排列.

 

 

以X横坐标中间的点作为分界线.将平面的点分成左边和右边,以上图为例,分为左边5个右边5个.

 

然后找到左边的点中最近点对的距离d1,和右边最近点对的距离d2。

 

令d=min{d1,d2}.

 

对位于【mid-d,mid+d】区间内的点对(该区间内的点对有可能距离小于d)进行距离讨论,注意要先按y坐标排序,for循环遍历每个点,循环过程中只需要讨论每个点上下距离为d的点对(即竖直距离大于d时continue)(情况复杂,详见代码),最后视情况更新d

 1 #include <iostream>  
 2 #include <cstdio>  
 3 #include <cstring>  
 4 #include <cmath>  
 5 #include <algorithm>  
 6 using namespace std;
 7 const double inf = 1e20;
 8 const int maxn = 100005;
 9 
10 struct Point{
11     double x, y;
12 }point[maxn];
13 
14 int n, mpt[maxn];
15 
16 
17 //以x为基准排序
18 bool cmpxy(const Point& a, const Point& b){
19     if (a.x != b.x)
20         return a.x < b.x;
21     return a.y < b.y;
22 }
23 
24 bool cmpy(const int& a, const int& b){
25     return point[a].y < point[b].y;
26 }
27 
28 double min(double a, double b){
29     return a < b ? a : b;
30 }
31 
32 double dis(int i, int j){
33     return sqrt((point[i].x - point[j].x)*(point[i].x - point[j].x) + (point[i].y - point[j].y)*(point[i].y - point[j].y));
34 }
35 
36 double Closest_Pair(int left, int right){
37     double d = inf;
38     if (left == right)
39         return d;
40     if (left + 1 == right)
41         return dis(left, right);
42     int mid = (left + right) >> 1;
43     double d1 = Closest_Pair(left, mid);
44     double d2 = Closest_Pair(mid + 1, right);
45     d = min(d1, d2);
46     int i, j, k = 0;
47     //分离出宽度为d的区间  
48     for (i = left; i <= right; i++){
49         if (fabs(point[mid].x - point[i].x) <= d)
50             mpt[k++] = i;
51     }
52     sort(mpt, mpt + k, cmpy);
53     //线性扫描  
54     for (i = 0; i < k; i++){
55         for (j = i + 1; j < k && point[mpt[j]].y - point[mpt[i]].y<d; j++){
56             double d3 = dis(mpt[i], mpt[j]);
57             if (d > d3)    d = d3;
58         }
59     }
60     return d;
61 }
62 
63 int main(){
64     while (~scanf("%d", &n) && n){
65         for (int i = 0; i < n; i++)
66             scanf("%lf %lf", &point[i].x, &point[i].y);
67         sort(point, point + n, cmpxy);
68         printf("%.2lf\n", Closest_Pair(0, n - 1) / 2);
69     }
70     return 0;
71 }

代码转载16:23:112018-07-11https://www.cnblogs.com/zyxStar/p/4591897.html

 

转载于:https://www.cnblogs.com/guguchen/p/9295189.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值