最も近い点の平面

タイトル説明

同一平面上にn個の点を与える、最も近い点をから得られます

ポータル

問題の解決策

ここでは、人間の慣行のようなものの本質を議論しない:ランダムな回転を

パーティション考えてみましょう
再び注文プレスの全体のポイントのシーケンスを最初の行をxの
あなたが分割し、征服したい場合は、明らか合併で別の特定の部分に対処するために、
x座標半分によると、私たちは直接の半分を検討した後、それぞれ、二つの部分から最近取得しましたその後、マージ

その後、我々は合併行う方法
マージ処理では、我々は考慮する必要があり、ちょうど我々の2つの半ばの状況間の分離の点にがあるかもしれません
、我々はリミット暴力を見つけるためにビットを追加しますので、

コード

#include<bits/stdc++.h>
using namespace std;
#define re register
#define in inline
#define ll long long
#define db double
#define get getchar()
in int read()
{
    int t=0; char ch=get;
    while(ch<'0' || ch>'9') ch=get;
    while(ch<='9' && ch>='0') t=t*10+ch-'0', ch=get;
    return t;
}
const int _=3e5+9; 
int n;
struct yzx{
    db y,x;
}a[_];
in db dis(yzx a,yzx b)
{
    return sqrt(abs(a.x-b.x)*abs(a.x-b.x)+abs(b.y-a.y)*abs(b.y-a.y));
}
in int cmp1(int x,int y)
{
    return a[x].y<a[y].y;
}
int num[_];  
in db work(int l,int r)
{
    db  ans=1000000009;
    if(l==r)
        return ans;
    if(l+1==r)
        return dis(a[l],a[r]);
    int mid=l+r>>1;
    ans=min(work(l,mid),work(mid+1,r));
    int cnt=0;
    for(re int i=l;i<=r;i++)
    if(abs(a[i].x-a[mid].x)<=ans) num[++cnt]=i;
    sort(num+1,num+cnt+1,cmp1);
    for(re int i=1;i<cnt;i++)
        for(re int j=i+1;j<=cnt&&abs(a[num[j]].y-a[num[i]].y)<ans;j++)
            ans=min(ans,dis(a[num[i]],a[num[j]]));
    return ans;
}
in int cmp(yzx x,yzx y) {
    if (x.x == y.x)
        return x.y < y.y;
    else
        return x.x < y.x;
}
int main()
{
    n=read();
    for(re int i=1;i<=n;i++)
        a[i].x=read(),a[i].y=read();
    sort(a+1,a+n+1,cmp);
    printf("%.4lf\n",work(1,n));
}

おすすめ

転載: www.cnblogs.com/yzhx/p/11706686.html
おすすめ