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

  • 相关阅读:
    grunt in webstorm
    10+ Best Responsive HTML5 AngularJS Templates
    响应式布局
    responsive grid
    responsive layout
    js event bubble and capturing
    Understanding Service Types
    To add private variable to this Javascript literal object
    Centering HTML elements larger than their parents
    java5 新特性
  • 原文地址:https://www.cnblogs.com/CKboss/p/3351142.html
Copyright © 2011-2022 走看看