zoukankan      html  css  js  c++  java
  • 平面最近点对模板

    导论书上几何部分有讲 二分递归算法 将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  两种点集间的

  • 相关阅读:
    可恶的Desktop_1.ini 规格严格
    BoundChecker 规格严格
    MySQL NetFlow Analysiser 忘记密码(转载) 规格严格
    Oracle 基本查询 规格严格
    NAN 规格严格
    面试题:为什么java不允许 super.super.xxx 这样的语句?
    国人眼中的Scrum
    NetBeans 时事通讯(刊号 # 1 Apr 02, 2008)
    面试题:为什么java不允许 super.super.xxx 这样的语句?
    快来测试你的脑年龄
  • 原文地址:https://www.cnblogs.com/shangyu/p/3877745.html
Copyright © 2011-2022 走看看