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;
    }

  • 相关阅读:
    P1128 [HNOI2001]求正整数
    zabbix-server端监控MySQL服务
    对服务器磁盘、CPU、内存使用状态,设置163邮件告警
    JDK8 的FullGC 之 metaspace
    JDK8-废弃永久代(PermGen)迎来元空间(Metaspace)
    JVM的方法区和永久带是什么关系?
    如何使用start with connect by prior递归用法
    JVM原理讲解和调优
    jvm 性能调优工具之 jstat
    记一次HBase内存泄漏导致RegionServer挂掉问题
  • 原文地址:https://www.cnblogs.com/CKboss/p/3351142.html
Copyright © 2011-2022 走看看