最近对算法

Posted powerkeke

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了最近对算法相关的知识,希望对你有一定的参考价值。

1. 问题

  p1=(x1,y1),p2=(x2,y2)...pn=(xn,yn)是平面nn个点构成的集合S,最近对问你就是找出集合S中距离最近的点对。

 

2. 解析

  采用分治法。

   1)划分:将集合S分成两个子集S1S2,根据平衡子问题原则,每个子集中大约有n/2个点,设集合S的最近点对是pipj(1<=i,j<=n

  则有以下三种情况 1.piS1,pjS1

             2.piS1,pjS2

                          3.piS2, pjS2

  (2)求解子问题:对于划分阶段的情况12可递归求解

    通过直线x=M(中位数),将空间划为两部分,x<Mx>M分别求出左右最近点对距离,d1,d2,d=min(d1,d2)则,只需考虑3,x-dxd的区域之间的最近点对,按照Y坐标对区域内点进行排序,如果一个点对的距离小于d,他们一定在d*(2*d)的区域内。

 

3. 设计

  1.预处理:对点集合S={(x1,y1),(x2,y2)......(xn,yn)}按照x坐标升序排列

  2.如果n=2,则返回连点之间距离

  3.计算{(x1,y1),(x2,y2).....(xm,ym)}之间的最近距离d1

    计算{(xm,ym)(xm+1,ym+1)....(xn,yn)}之间的最近距离d2

    d=min(d1,d2)

  4.依次计算S[l...r]的最近点对(将集合按照y升序排列,考察y-s[m].y<d的点)

    l=min(i)| S[m]-S[i]<d

    r=max(i)| S[i]-S[m]<d

 

4. 分析

  O(nlogn)

 

5. 源码

/*
author: keke
project name:最近对算法 
Time Complexity: O(nlogn)
*/
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <algorithm>
#include <cmath>
using namespace std;
const double eps = 1e-8;
const int INF = 0x7fffffff;
int n;
struct Point {
    double x,y;
    Point(double x=0, double y=0):x(x),y(y) {}
    bool operator < (const Point& p) const {
        if(x != p.x)return x < p.x;
        else return y < p.y;
    }
} p[200000+5],temp[200000+5];
bool cmpy(Point a, Point b) {
    return a.y < b.y;
}
double Dis(Point a, Point b) {
    return sqrt((a.x-b.x)*(a.x-b.x) + (a.y-b.y)*(a.y-b.y));
}
double Closest_Pair(int left, int right) {
    double d = INF;
    if(left == right)
        return d;
    if(left +1 == right)
        return Dis(p[left],p[right]);
    int mid = (left+right)>>1;
    double d1 = Closest_Pair(left,mid);
    double d2 = Closest_Pair(mid,right);
    d = min(d1,d2);
    int k = 0;
    for(int i = left; i <= right; i++) {
        if(fabs(p[mid].x - p[i].x) <= d)
            temp[k++] = p[i];
    }
    sort(temp,temp+k,cmpy);
    for(int i = 0; i < k; i++) {
        for(int j = i+1; j < k && temp[j].y - temp[i].y < d; j++) {
            double d3 = Dis(temp[i],temp[j]);
            d = min(d,d3);
        }
    }
    return d;
}
int main() {
    cin>>n;
    for(int i=0; i<n; i++) {
        double a,b;
        scanf("%lf%lf",&a,&b);
        p[i] = Point(a,b);
    }
    sort(p,p+n);
    printf("%.3f",Closest_Pair(0,n-1));
}

 

 

 

以上是关于最近对算法的主要内容,如果未能解决你的问题,请参考以下文章

以下代码片段的算法复杂度

有人可以解释啥是 SVN 平分算法吗?理论上和通过代码片段[重复]

片段(Java) | 机试题+算法思路+考点+代码解析 2023

可以解密加密数据的片段吗?

编程思想与算法

Python 和 C++ 下字符串查找速度对比,你觉得Python适合算法竞赛吗