zoukankan      html  css  js  c++  java
  • 平面中最近的两点(分治法)

          设平面上的点按x排序好了,这样最多增加O(N*logN),这再整个算法来看并没有增加复杂度级别。
           排好序后,可以划一条垂线,把点集分成两半:PL和PR。于是最近点对或者在PL中,或者在PR中,或者PL,PR各有一点。
           把三种距离情况定义为dL, dR, dC.
     
            平面中最近的两点(分治法) - qhn999 - 码代码的猿猿     
           其中dL, dR可以递归求解,于是问题就变为计算dC。 根据上面红色字解释,由于我们希望得到O(N*logN)的解,因此必须能够仅仅多花O(N)的附加工作计算dC。
           另s=min(dL, dR). 通过观察能得出结论:如果dC<s,即dC对s有所改进,则只需计算dC。如果dC满足这样的条件,则决定dC的两点必然在分割线的s距离之内,称之为带(strip)
           否则不可能满足dC<s, 于是缩小了需要考虑的点的范围。      
             平面中最近的两点(分治法) - qhn999 - 码代码的猿猿
           如果是均匀分布的点集,则能证明出在该带中平均只有O(sqrt(N))个点,(注:书上这么写的,我也不会证,先记下这个理论吧)。因此,对这些点运用蛮力法可以在O(N)时间内完成。

    #include <iostream>
    #include <algorithm>
    #include <cmath>
    #include <iomanip>

    #define MM 100020
    using namespace std;

    struct Note
    {
        double x;
        double y;
    }pt[MM];

    int _sort1[MM];
    int _sort2[MM];

    double min(double& x,double& y)
    {
        if(x-y>=1e-6)
           return y;
        else return x;
    }

    int cmp_x(const void *a,const void *b)
    {
        if(((Note*)a)->x>((Note*)b)->x)  return 1;
        else return -1;
    }

    int cmp_y(const void *a,const void *b)
    {
        if(((Note*)a)->y>((Note*)b)->y)  return 1;
        else return -1;
    }
    double distan(Note a,Note b)
    {
        return sqrt((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y));
    }

    double neardis(int first,int ends)
    {
        if(ends-first==1)  return distan(pt[first],pt[ends]);
        if(ends-first==2)  return min(min(distan(pt[first],pt[first+1]),distan(pt[first],pt[ends])),distan(pt[first+1],pt[ends]));
    //2个点或3个点情况下返回
        int mid=(first+ends)/2;
        double dis1=neardis(first,mid);
        double dis2=neardis(mid+1,ends);
    //划分问题
        double dota=min(dis1,dis2); 
        int _end1=0;
        int _end2=0;

        for(int i=mid;i>first&&distan(pt,pt[mid])<=dota;i--)
        {
            _sort1[_end1++]=i;
        }
        for(int i=mid+1;i<ends&&distan(pt,pt[mid])<=dota;i++)
        {
            _sort2[_end2++]=i;
        }
    //统计在分界线两边的点的情况;
        double min_dis=dota;

        for(int i=0;i<_end1;i++)
        {
            for(int j=0;j<_end2;j++)
            {
                dota=distan(pt[_sort1],pt[_sort2[j]]);
                min_dis=min(min_dis,dota);
            }
        }
    //计算在分界线两边的点的距离,与最小距离比较。
        return min_dis;
    }

    int main()
    {
        int n;
        cin>>n;
        while(n)
        {
            for(int i=0;i<n;i++)
                cin>>pt.x>>pt.y;
            qsort(pt,n,sizeof(pt[0]),cmp_x);
            cout<<fixed<<setiosflags(ios::showpoint)<<setprecision(2)<<neardis(0,n-1)<<endl;
            cin>>n;
        }
        return 0;
    }

  • 相关阅读:
    WPF 使用 Direct2D1 画图 绘制基本图形
    WPF 使用 Direct2D1 画图 绘制基本图形
    dot net core 使用 IPC 进程通信
    dot net core 使用 IPC 进程通信
    win2d 图片水印
    win2d 图片水印
    Java实现 LeetCode 240 搜索二维矩阵 II(二)
    PHP closedir() 函数
    PHP chroot() 函数
    PHP chdir() 函数
  • 原文地址:https://www.cnblogs.com/CKboss/p/3351142.html
Copyright © 2011-2022 走看看