平面最近点对模板

导论书上几何部分有讲 二分递归算法 将p数组分为左右两部分 分别递归求出两部分的最小距离 然后再求出左右之间的最小距离 取其最小。

因为左右的最小距离minz已经求出,在求它俩部分之间的最小距离时就有了限制,fabs(x1-x2)<minz fabs(y1-y2)<minz 可以证明出需要用到的点是小于等于8个的,导论上有证。

开两个按x排序的数组和按y排序的数组加快分块的速度;

复杂度n*log(n)

几篇讲的不错的博客

讲解很清晰http://blog.csdn.net/zmlcool/article/details/6727377

有图更好理解 http://blog.csdn.net/guyulongcs/article/details/6841550

struct point
{
    double x,y;
    int id;
    //int flag;
    point(double x=0,double y =0):x(x),y(y) {}
} p[N],pp[N],py[N];
typedef point pointt;
pointt operator -(point a,point b)
{
    return point(a.x-b.x,a.y-b.y);
}
double dis(point a,point b)
{
    // if(a.flag==b.flag) return INF;//适于两种不同点集间的最小距离
    return sqrt((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y));
}
bool cmp(point a,point b)
{
    return a.x<b.x;
}
bool cmpp(point a,point b)
{
    return a.y<b.y;
}
void binmerge(point py[],point pp[],int l,int m,int r)
{
    int i,j,g=l;
    for(i = l,j = m+1 ; i <= m&&j <= r ;)//将pp中两块有序的集合 合并为一个有序的集合
        if(pp[i].y<pp[j].y) py[g++] = pp[i++];
        else py[g++] = pp[j++];

    while(i<=m) py[g++] = pp[i++];
    while(j<=r) py[g++] = pp[j++];
    //memcpy(pp + l, py + l, (r - l + 1) *sizeof(py[0]));
}
double binshortest(point p[],point pp[],point py[],int l,int r)
{
    if(r-l==1) return dis(p[l],p[r]);
    if(r-l==2) return min(min(dis(p[l],p[r]),dis(p[l],p[l+1])),dis(p[l+1],p[r]));
    int mid = (l+r)>>1;
    int i,j,g = l,o = mid+1;
    for(i = l ; i <= r ; i++)
    {
        if(py[i].id<=mid)//按y坐标顺序将点划分到pp左半数组
            pp[g++] = py[i];
        else
            pp[o++] = py[i];//pp右半数组
    }
    double minz = min(binshortest(p,py,pp,l,mid),binshortest(p,py,pp,mid+1,r));
    binmerge(py,pp,l,mid,r);
    g = l;
    for(i = l ; i <= r ; i++)//找到x坐标满足到中心线距离小于minz的点
        if(fabs(py[i].x-py[mid].x)<minz) pp[g++] = py[i];
    for(i = l ; i < g ; i++)
    {
        for(j = i+1 ; j < g && fabs(pp[i].y-pp[j].y)<minz; j++)//加上y坐标上的限制
            minz = min(dis(pp[i],pp[j]),minz);
    }
    return minz;
}
void solve(point p[])
{
    sort(p,p+n,cmp);
    for(int i = 0; i < n ; i++)
        p[i].id = i;
    memcpy(py,p,n*sizeof(py[0]));
    sort(p,p+n,cmpp);
    double ans = binshortest(p,pp,py,0,n-1);
}

 例题

hdu1007  直接模板

poj3714  两种点集间的

原文地址:https://www.cnblogs.com/shangyu/p/3877745.html