分治算法
分:递归解决较小问题
治:然后,从子问题的解构建原问题的解
我们仿照一维的情况先把所有点按照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