2013-team5/minpair

从 Trac 迁移的文章

这是从旧校内 Wiki 迁移的文章,可能存在一些样式问题,您可以向 memset0 反馈。

原文章内容如下:

=== 求二维平面最近点对 ===

{{{
#include <iostream>
#include <cstdio>
#include <cmath>
#include <algorithm>
using namespace std;
const double INF=1e30;
struct point{ double x,y; };
inline double sqr(double x){ return x * x; }
inline double dis(point a,point b){ return sqrt(sqr(a.x-b.x)+sqr(a.y-b.y)); }
inline int cmpx(point a,point b){ return a.x<b.x || a.x==b.x && a.y<b.y; }

class Minpair{
public:
    static const int SIZE=100005;//数据范围
    point X[SIZE],Y[SIZE],Q[SIZE];
    int tot;
    double res;
    void clear(){ tot=0; }//清空
    inline void add(point a){ X[tot]=a; tot++; }//加入一个点
    double divide(int l,int r,point &a,point &b){
        if (l>=r) return INF;
        int m=(l+r)>>1;
        double xl=X[m+1].x,xr=X[m].x;
        divide(l,m,a,b);
        divide(m+1,r,a,b);
        int tl=l,tr=m+1;
        for (int i=l; i<=r; i++)
            if (tr>r || tl<=m && X[tl].y<X[tr].y)
                Y[i]=X[tl++];
            else
                Y[i]=X[tr++];

        xl-=res; xr+=res;
        int ll=0,rr=-1;
        for (int i=l; i<=r; i++)
            if (xl<Y[i].x && Y[i].x<xr){
                while(ll<=rr && Y[i].y-Q[ll].y>=res) ll++;
                for (int j=ll; j<=rr; j++){
                    double tmp=dis(Y[i],Q[j]);
                    if (tmp<res){
                        res=tmp;
                        a=Y[i]; b=Q[j];
                    }
                }
                Q[++rr]=Y[i];
            }
        for (int i=l; i<=r; i++) X[i]=Y[i];
        return res;
    }
    double Mindis(point& a,point& b){//最近点对返回到point a,b. 返回值为a,b之间的距离
        sort(X,X+tot,cmpx);
        res=INF;
        return divide(0,tot-1,a,b);
    }
};
}}}

{{{
///zoj2107, 800ms 

Minpair P;

int main(){
    int n;
    while (scanf("%d",&n)!=EOF){
        if (n==0) break;
        P.clear();
        for (int i=0; i<n; i++){
            point a;
            scanf("%lf%lf",&a.x,&a.y);
            P.add(a);
        }
        point a,b;
        printf("%.2lf\n",P.Mindis(a,b)/2.0);
    }
    return 0;
}
}}}

求二维平面最近点对

#include <iostream>
#include <cstdio>
#include <cmath>
#include <algorithm>
using namespace std;
const double INF=1e30;
struct point{ double x,y; };
inline double sqr(double x){ return x * x; }
inline double dis(point a,point b){ return sqrt(sqr(a.x-b.x)+sqr(a.y-b.y)); }
inline int cmpx(point a,point b){ return a.x<b.x || a.x==b.x && a.y<b.y; }
class Minpair{
public:
    static const int SIZE=100005;//数据范围
    point X[SIZE],Y[SIZE],Q[SIZE];
    int tot;
    double res;
    void clear(){ tot=0; }//清空
    inline void add(point a){ X[tot]=a; tot++; }//加入一个点
    double divide(int l,int r,point &a,point &b){
        if (l>=r) return INF;
        int m=(l+r)>>1;
        double xl=X[m+1].x,xr=X[m].x;
        divide(l,m,a,b);
        divide(m+1,r,a,b);
        int tl=l,tr=m+1;
        for (int i=l; i<=r; i++)
            if (tr>r || tl<=m && X[tl].y<X[tr].y)
                Y[i]=X[tl++];
            else
                Y[i]=X[tr++];
        xl-=res; xr+=res;
        int ll=0,rr=-1;
        for (int i=l; i<=r; i++)
            if (xl<Y[i].x && Y[i].x<xr){
                while(ll<=rr && Y[i].y-Q[ll].y>=res) ll++;
                for (int j=ll; j<=rr; j++){
                    double tmp=dis(Y[i],Q[j]);
                    if (tmp<res){
                        res=tmp;
                        a=Y[i]; b=Q[j];
                    }
                }
                Q[++rr]=Y[i];
            }
        for (int i=l; i<=r; i++) X[i]=Y[i];
        return res;
    }
    double Mindis(point& a,point& b){//最近点对返回到point a,b. 返回值为a,b之间的距离
        sort(X,X+tot,cmpx);
        res=INF;
        return divide(0,tot-1,a,b);
    }
};
///zoj2107, 800ms 
Minpair P;
int main(){
    int n;
    while (scanf("%d",&n)!=EOF){
        if (n==0) break;
        P.clear();
        for (int i=0; i<n; i++){
            point a;
            scanf("%lf%lf",&a.x,&a.y);
            P.add(a);
        }
        point a,b;
        printf("%.2lf\n",P.Mindis(a,b)/2.0);
    }
    return 0;
}