[Explain] the book on the plane closest point

Give you n points on a two-dimensional plane, which lets you find the nearest point pair.

【answer】


It is a question of partition.
Can be done:
First, in accordance with row x n points in ascending order.
Then the points within this interval is divided into l..r
l..mid two portions and mid + 1..r recursive solution.
Distances d1 and d2 are determined these two points inside the closest point
and so d = min (d1, d2)
which is the last point in answer to the case where one side.
In the case of each of the left and right interval interval p1 and p2 now consider the answer to the last point.
First, the left and right sections midpoint interval abscissa and the parting line over a distance d of point may be removed.
Then for each of p1, a length d, a rectangle on the right side of the drawing a high 2d.
You will find at most, only six points in the right range (the pigeonhole principle) within that rectangle
so we only need to point within this interval row l..r look like according to the y-axis in ascending order.
Then like. For each point (X, y) of the other inspection range y coordinate point (yd, y + d) is
, but this sort of case, the time complexity of n- logN logN level.
We can answer during the merger of the time, the way to do something for each subinterval merge sort (in accordance with the y-axis).
Then merge sort when left to point range, by the way traversal and its y coordinate of the absolute value of the difference is less than d the other point to
this is the time complexity level of the n * logn

[Code]

#include <cstdio>
#include <cmath>
using namespace std;

const int N = 1e5;
const int oo = 1e9;

struct abc{
    int x,y;
};

int n;
abc a[N+10];
abc b[N+10];

int sqr(int x){return x*x;}

int dis(abc a,abc b){
    return sqr(a.x-b.x)+sqr(a.y-b.y);
}

int min(int x,int y){
    if (x<y) return x;else return y;
}

int divide(int l,int r){
    if (l>=r) return oo;
    int mid = (l+r)>>1;abc mp = a[mid];
    int d = divide(l,mid);d = min(d,divide(mid+1,r));
    int i = l,j = mid + 1,k = l;
    while (i<=mid || j<=r){
        while (j<=r && (i>mid || a[j].y<=a[i].y)) b[k++] = a[j++];
        if (i<=mid && mp.x-a[i].x<d){//a[i]是分割线左边的点
            //此时a[mid+1..j-1]全都小于等于a[i]的纵坐标
            //a[j..r]全都大于a[i]的纵坐标。(且这两段的点都是分割线右边的点)
            for (int l = j-1;l>=mid+1;l--){
                if (sqr(a[i].y-a[l].y)>d) break;
                int temp = dis(a[l],a[i]);
                d = min(temp,d);
            }
            for (int l = j;l<=r;l++){
                if (sqr(a[l].y-a[i].y)>d) break;
                int temp = dis(a[l],a[i]);
                d = min(temp,d);
            }
        }
        if (i<=mid) b[k++] = a[i++];
    }
    for (int i = l;i<= r;i++) a[i] = b[i];
    return d;
}

void _swap(abc *x,abc *y){
    abc t = *x;
    *x = *y;
    *y = t;
}

void kp(abc a[],int l,int r){
    abc temp = a[l];
    int i = l,j = r+1;
    while(true){
        while (a[++i].x<temp.x && i<r);
        while (a[--j].x>temp.x);
        if (i>=j) break;
        _swap(&a[i],&a[j]);
    }
    a[l] = a[j];
    a[j] = temp;
    if (l<j) kp(a,l,j-1);
    if (j<r) kp(a,j+1,r);
}

int main(){
    scanf("%d",&n);
    for (int i = 1;i <= n;i++) scanf("%d%d",&a[i].x,&a[i].y);
    kp(a,1,n);
    double ans = sqrt(1.0*divide(1,n));
    printf("%.3f\n",ans);
    return 0;
}

Guess you like

Origin www.cnblogs.com/AWCXV/p/11622575.html