飛行機の最も近い点に本を[説明]

あなたは、最寄りのポイントのペアを見つけることができます2次元平面上であなたn個の点を与えます。

[説明]


これは、パーティションの問題です。
行うことができる:
まず、昇順で行×nの点に従って。
この区間内の点はl..rに分割されている
+ 1..r再帰溶液二つの部分との中間をl..mid。
距離d1及びd2は、これら二つの点の最も近い点の内側に決定される
ので、D =分(D1、D2)
片側場合に答えの最後の点です。
左右の間隔間隔P1、P2のそれぞれの場合には、今最後の点に対する回答を検討してください。
まず、左右のセクションでは、間隔横軸を中点と点の距離dにわたって分割線を除去することができます。
次いで、P1のそれぞれについて、長さd、高い2D描画の右側の矩形。
あなたは、その矩形内右の範囲(鳩の巣原理)で、せいぜい6点を見つけます
ので、我々は唯一の昇順にy軸に応じて次のようになりl..rこの間隔行内にポイントする必要があります。
次にたい。Yが点(YD、Y + d)は座標他の検査範囲の各点(X、Y)について
、しかしケースのこの種、N-の時間複雑logN個 logN個のレベル。
我々は、各サブインターバルのために何かをする方法は、(y軸に応じて)ソートマージ、時間の合併時に答えることができる
D未満である方法によってトラバーサルとyは差の絶対値の座標、ポイント範囲左ときにマージソート他のポイント
これは、n *のLOGNの時間複雑さのレベルであります

[コード]

#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;
}

おすすめ

転載: www.cnblogs.com/AWCXV/p/11622575.html