zoukankan      html  css  js  c++  java
  • 最接近的点配对(分治问题理解) && HDU 1007代码

    题目大意:

    给定一堆点集,在这一堆点集中找到一组点集它们之间的距离达到最短

    对于HDU1007因为求圆的半径,所以距离还要除以2

    普通情况下,可以将nge点,将任意两个点之间的距离都算一遍,在循环过程中,每次取到距离的较小值

    但数据量大的话,这种O(n^2)的方法肯定是不合理的

    转化为O(nlogn)的方法是可取的

    这里采用分治的方法

    我们希望尽可能的均匀分配,也就是让左右两端所含有的点的数目一样多,所以一开始就根据以x优先排序 , 然后取中值作为分割边

    int fenzhi(int l , int r)

    {

      int m = (l+r) >> 1;

      int d1 = fenzhi(l , m);

      int d2 = fenzhi(m+1 , r);

      int d3 = 左右两部分的点相互作距离运算得到  //也就是一个合并的过程

      return min(d1 , d2 , d3);

    }

    当l == r时 无疑距离不存在,我们返回一个最大值maxn即可不会影响结果

    当l == r-1说明只存在两个点, 那就是将这两个点的距离作为最短距离返回即可

    由于是自底向下

    我们可以根据d1 , d2 , 优先得到d = min(d1 , d2)

    那样我们在合并的过程中只要找距离小于d的点就可以了,我们不能将所有点都访问一遍,但是我们可以控制一个范围

    先找到所有离分割线距离小于d的点,也即左侧的图所示,超出那个范围的话必然左右两个点相连距离大于d

    找到所有符合点将其下标用rec数组保存即可

    然后将rec数组中的点全都比较一遍,比较过程中可以先只关注两点在y轴上的距离是否小于d , 是的话计算距离,并且与原距离取最小值

     1 #include <cstdio>
     2 #include <cstring>
     3 #include <cmath>
     4 #include <iostream>
     5 #include <algorithm>
     6 using namespace std;
     7 #define N 100005
     8 #define maxn 2000000000
     9 
    10 struct Point{
    11     double x , y;
    12     //利用减法运算计算两点间的距离
    13     double operator-(const Point &m)const{
    14         return sqrt((x-m.x)*(x-m.x) + (y-m.y)*(y-m.y));
    15     }
    16 }p[N];
    17 
    18 bool cmpxy(const Point &m1 , const Point &m2){
    19     if(m1.x == m2.x) return m1.y < m2.y;
    20     return m1.x < m2.x;
    21 }
    22 
    23 //d要随之更改,所以参数要引用传递
    24 void merge_l_r(double &d , int l , int r)
    25 {
    26     int m = (l+r) >> 1;
    27     /*得到所有离分割线距离不大于d的点,否则本身到分割线就大于d,那么左右两侧相连必然大于d
    28     就没有保留下去的必要了*/
    29     int rec[N] , k = 0;//记录所有符合点的编号
    30     for(int i = l ; i<=r ; i++){
    31         if(p[m] - p[i] < d)
    32             rec[k++] = i;
    33     }
    34     
    35     //有见到别人博客在这里将rec根据对应点的y的大小排了一次序,但我提交了好像时间反而更长就干脆不用了
    36     /*
    37     大致如下:
    38     现在最外面写个
    39     bool cmpxy(const Point &m1 , const Point &m2){
    40         if(m1.x == m2.x) return m1.y < m2.y;
    41         return m1.x < m2.x;
    42     }
    43     这个位置写个sort(rec , rec+k , cmpy);
    44     */
    45     for(int i=0 ; i<k ; i++){
    46         for(int j=i+1 ; j<k ; j++){
    47             if(abs(p[rec[j]].y - p[rec[i]].y) < d)
    48                 d = min(d , p[rec[j]] - p[rec[i]]);
    49         }
    50     }
    51 }
    52 
    53 double fenzhi(int l , int r)
    54 {
    55     int m = (l+r) >> 1;
    56     //这里是计算两点的最短距离,l==r只有一个点存在,所以输出一个最大距离使其不影响结果
    57     if(l == r) return maxn;
    58     if(l == r-1) return p[l] - p[r];
    59 
    60     double d;
    61     //处理左边
    62     double d1 = fenzhi(l , m);
    63     //处理右边
    64     double d2 = fenzhi(m+1 , r);
    65     //得到左右两部分中两点间的最小值
    66     d = min(d1 , d2);
    67 
    68     //将这个最小值和左右两部分的点相连得到的最小边作比较
    69     merge_l_r(d , l , r);
    70 
    71     return d;
    72 }
    73 
    74 int main()
    75 {
    76     int n;
    77     while(scanf("%d" , &n) , n){
    78         for(int i = 0 ; i<n ; i++){
    79             scanf("%lf%lf" , &p[i].x , &p[i].y);
    80         }
    81         sort(p , p+n , cmpxy);
    82         //这里是取圆的半径所以除以二
    83         printf("%.2f
    " , fenzhi(0 , n-1) / 2);
    84     }
    85     return 0;
    86 }

      

  • 相关阅读:
    Web网页数据抽取软件的设计与实现
    以Groovy的方式更稳定地解析HTML(转载)
    HTML 资讯汲取(上篇) 使用 JDOM 、 TagSoup 及 XPath
    html解析
    HTML 資訊汲取(下篇) TagSoup 輸出 namespace 問題的解決方案
    国外免费主机空间
    ASP.NET获取客户端IP地址、系统版本、浏览器版本
    阁下莫非就是当年华山论剑武功独步天下罕有其匹号称一朵梨花压海棠的少林寺智障大师收养的小沙弥低能的爱犬旺财踩扁的蟑螂小强曾滚过的一个粪球?
    html中table里的col标签
    Visual Studio 2010 中的 TODO
  • 原文地址:https://www.cnblogs.com/CSU3901130321/p/4178000.html
Copyright © 2011-2022 走看看