分治法求最近点对

#include<iostream>
#include<algorithm>
#include<vector>
#include<cmath>
using namespace std;
typedef struct Node
{
    int x;
    int y;
};
bool CmpX(Node a,Node b)
{
    return a.x<b.x;
}
double Distance(Node a,Node b)
{
    int xx=a.x-b.x;
    int yy=a.y-b.y;
    double distance=xx*xx+yy*yy;
    return sqrt(distance);
}
double dfs(Node arr[],int low,int high)
{
    double result=0.0;
    if((high-low)<3){
        if((high-low)==1){
            double distance=Distance(arr[low],arr[high]);
            return distance;
        }
        else{
            double distance1=Distance(arr[low],arr[low+1]);
            double distance2=Distance(arr[low],arr[low+2]);
            double distance3=Distance(arr[low+1],arr[low+2]);
            return min(distance1,min(distance2,distance3));
        }
    }
    int mid=(low+high)/2;
    double left_result=dfs(arr,low,mid);
    double right_result=dfs(arr,mid+1,high);
    double vec=min(left_result,right_result);
    result=vec;
    vector<Node> s;
    for(int i=low;i<=high;i++){//把这中间区域范围的数拿出来,看看会不会出现更小的。
        if((arr[i].x>arr[mid].x-vec)&&(arr[i].x<arr[mid].x+vec)){
            s.push_back(arr[i]);
        }
    }
    sort(s.begin(),s.end(),CmpX);
    int size=s.size();
    for(int i=0;i<size;i++){
        int k=(i+7)>size?size:(i+7);
        for(int j=i+1;j<k;j++){
             if(Distance(s.at(i),s.at(j))<result){
                result=Distance(s.at(i),s.at(j));
             }
        }
    }
    return result;
}
int main()
{
    int N;
    cin >> N;
    Node arr[N];
    for(int i=0;i<N;i++){
       cin >> arr[i].x >> arr[i].y;
    }
    double rev=dfs(arr,0,N-1);
    cout << rev;
}

不断地二分直到三个点时或者两个点时,直接算出他们之间的距离,不断地从两边考虑它们距离的最小值,但是还要考虑第三种情况,那就是一边各一个点,这种情况不能排除在外。

原文地址:https://www.cnblogs.com/sddr/p/10701907.html