zoukankan      html  css  js  c++  java
  • 计算几何 平面最近点对 nlogn分治算法 求平面中距离最近的两点

    平面最近点对,即平面中距离最近的两点

    分治算法:

    int SOLVE(int left,int right)//求解点集中区间[left,right]中的最近点对

    {

        double ans; //answer

        0)    调用前的预处理:对所有点排序,以x为第一关键词y为第二关键字 , 从小到大;

        1)    将所有点按x坐标分成左右两部分;

     

        /*      分析当前集合[left,right]中的最近点对,有两种可能:

              1. 当前集合中的最近点对,点对的两点同属于集合[left,mid]同属于集合[mid,right]

                 则ans = min(集合1中所有点的最近距离, 集合2中所有点的最近距离)

              2. 当前集合最近点对中的两点分属于不同集合:[left,mid][mid,right]

                  则需要对两个集合进行合并,找出是否存在p∈[left,mid],q∈[mid,right],使得distance(p,q)小于当前ans(即步骤1中求得的ans);

        */

        2)    Mid = (left+right)/2;

              ans = min( SOLVE(left,mid), SOLVE(mid,right) );

              即:递归求解左右两部分中的最近距离,并取最小值;

              //此步骤实现上文分析中的第一种情况

        /*      


     

              再次进行分析

              我们将集合[left,right]用x = mid这条直线分割成两部分

              则如果画出直线l1:x=mid-ans 和 l2:x=mid+ans,显然如果有p∈[left,mid], q∈[mid,right]且distance(p,q) < ans则p,q一定在直线l1和直线l2之间,否则distance(p,q)必定大于ans。

              于是扫描出在l1和l2之间的点

        */

        3)    建立缓存数组temp[];

              for i = left TO right

              {

                   如果 abs(Point[i].x - Point[mid].x) <= ans

                   则向temp中加入点Point[i];

               }

        /*

                对于temp中的点,枚举求所有点中距离最近两点的距离,然后与ans比较即可。

                枚举的时候不必两两枚举。观察下图中的点p

               不难发现,若有q∈[mid,mid+ans]使得distance(p,q) < ans,则q点的位置一定在图中画出的一个2ans×ansd的矩形中。可以证明点集[mid,mid+ans]中的、矩形外的点与p点的距离一定大于 ans。
               于是我们可以对temp以y为唯一关键字从小到大排序,进行枚举, 更新ans,然后在枚举时判断:一旦枚举到的点与p点y值之差大于ans,停止枚举。最后就能得到该区间的最近点对。

        */

        4)    sort(temp);

              for i = 0 TO k-1

              {

                    for j = i+1 TO k-1

                        如果 temp[j].y - temp[i].y >= ans  break;

                        ans = min( ans, distance(temp[i], temp[j]) );

               }

        5)    return ans;

    }


    算法的时间复杂度

            由鸽巢原理,代码中第四步的枚举实际上最多只会枚举6个点,效率极高(一种蒟蒻的证明请看下方的评论)

            本算法时间复杂度为O(n log n)

     

    代码:

     

     

    #include <stdio.h>
    #include <stdlib.h>
    #include <math.h>
    
    #define MIN( x , y ) ( (x) < (y) ? (x):(y) )
    
    struct _Point
    {
        long long x;
        long long y;
    }Points[100000] , Tmp[1000];
    
    int cmpxy ( const void *pa , const void *pb )
    {
        struct _Point *a = (struct _Point *)pa;
        struct _Point *b = (struct _Point *)pb;
        if ( a->x == b->x )
            return a->y > b->y ? 1:-1;
        else
            return a->x > b->x ? 1:-1;
    }
    
    int cmpy ( const void *pa , const void *pb )
    {
        struct _Point *a = (struct _Point *)pa;
        struct _Point *b = (struct _Point *)pb;
        
        return a->y > b->y ? 1:-1;
    }
    
    double dis ( struct _Point a , struct _Point b )
    {
        return sqrt ( (double) ( (a.x - b.x ) * ( a.x - b.x ) + ( a.y - b.y ) * ( a.y - b.y ) ) );
    }
    
    
    /*分治法求计算几何中平面点最近两点距离*/
    double min_length ( struct _Point *p , long left , long right )
    {
        double min;
        double d1,d2;
        long mid;
        long i , j ,k;
    
        if ( left == right )
            return -1;
    
        if ( left + 1 == right )
            return dis ( p[ left ] , p[ right ] );
    
        mid = ( left + right ) >> 1;
        d1 = min_length ( p , left , mid );
        d2 = min_length ( p , mid , right );
        min = MIN( d1 , d2 );
    
        for ( k = 0 , i = left ; i <= right ; i++ ) {
        
            if ( fabs ( p[i].x - p[mid].x ) <= min )
                Tmp[k++] = p[i];
        }
    
        qsort ( Tmp , k , sizeof ( Tmp[0] ) , cmpy );
        for ( i = 0 ; i < k - 1 ; i++ ) {
        
            for ( j = i + 1 ; j < k ; j++ ) {
            
                if ( fabs( Tmp[i].y - Tmp[j].y ) >= min )
                    break;
                
                min = MIN ( min , dis ( Tmp[i] , Tmp[j] ) );
            } 
        }
    
        return min;
    }
    
    int main ( int argc , char *argv[] )
    {
        long n;
        long i;
    
        scanf("%ld" , &n );
    
        for ( i = 0 ; i < n ; i++ )
            scanf ("%ld%ld" , &Points[i].x , &Points[i].y );
    
        qsort ( Points , n , sizeof ( Points[0] ) , cmpxy );
        printf ("%.3f" , min_length ( Points , 0 , n - 1 ) );
        return 0;
    }

    部分转载:http://blog.csdn.net/lytning/article/details/25370169

  • 相关阅读:
    NORDIC BLE MAC ADDR
    dbm和发射功率得对照表
    git切换账号邮箱
    文件编码问题造成的汉字输出乱码问题
    自定义printf 打印函数
    NORDIC 烧录BLE协议栈后不能用JLINK仿真bootloader问题及修改方案
    NORDIC BLE升级
    NORDIC ble RSSI
    NORDIC 错误文件
    NORDIC 协议栈下使用硬件定时器
  • 原文地址:https://www.cnblogs.com/rain-blog/p/acm-jisuanjihe.html
Copyright © 2011-2022 走看看