HDU1007Quoit Design(最小點對)

bigbigship發表於2014-10-04

題目連結:http://acm.hdu.edu.cn/showproblem.php?pid=1007

求所有點中最近兩點的距離的一半;最小點對(nlog (n))演算法模板題目;

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
using namespace std;

const int maxn = 100001;

struct point{
    double x,y;
}p[maxn],*a[maxn],*b[maxn];

bool cmpx (point *A,point *B)
{
    if(A->x==B->x)
        return A->y<B->y;
    return A->x<B->x;
}

bool cmpy (point *A,point *B)
{
    if(A->y==B->y)
        return A->x<B->x;
    return A->y<B->y;
}

inline double dis(point *a,point *b)
{
    return  sqrt((a->x-b->x)*(a->x-b->x)+(a->y-b->y)*(a->y-b->y));
}

inline double min(double a,double b)
{
    return a < b ? a : b;
}

double solve(int l,int r)
{
    if(l+1==r) return dis(a[l],a[r]);
    if(l+1==r) return min(dis(a[l],a[r]),min(dis(a[l],a[l+1]),dis(a[l+1],a[r])));
    int mid=(l+r)>>1;
    double ans=min(solve(l,mid),solve(mid,r));
    int i,j,cnt=0;
    for(int i=l;i<=r;i++){
        if(a[i]->x>=a[mid]->x-ans&&a[i]->x<=a[mid]->x+ans)
            b[cnt++]=a[i];
    }
    sort(b,b+cnt,cmpy);
    for(int i=0;i<cnt;i++){
        for(int j=i+1;j<cnt;j++){
            if(b[j]->y-b[i]->y>=ans)
                break;
            ans=min(ans,dis(b[i],b[j]));
        }
    }
    return ans;
}
int main()
{
    int n;
    while(~scanf("%d",&n)&&n!=0){
        for(int i=0;i<n;i++){
            scanf("%lf%lf",&p[i].x,&p[i].y);
            a[i]=&p[i];
        }
        sort(a,a+n,cmpx);
        printf("%.2lf\n",solve(0,n-1)/2);
    }
    return 0;
}


相關文章