5.分治法解最近对问题

分治法求最近对

1. 问题

设p1=(x1, y1), p2=(x2, y2), …, pn=(xn, yn)是平面上n个点构成的集合S,设计算法找出集合S中距离最近的点对。

2. 解析

可以划一条垂线,把点集分成两半:PL和PR。于是最近点对或者在PL中,或者在PR中,或者PL,PR各有一点。
把三种距离情况定义为dL, dR, dC.
其中dL, dR可以递归求解,于是问题就变为计算dC。
设s=min(dL, dR). 通过观察能得出结论:如果dC<s,则只需计算dC。如果dC满足这样的条件,则决定dC的两点必然在分割线的s距离之内,称之为带(strip)
否则不可能满足dC<s, 于是缩小了需要考虑的点的范围。

3. 设计

   int ClosestPoints(int n, int x[ ], int y[ ]){ 
   minDist=Double.POSITIVE_INFINITY;; 
   for (i=1; i< n; i++) 
      for (j=i+1; j<=n; j++) 
     { 
         d=(x[i]-x[j])* (x[i]-x[j])+(y[i]-y[j])* (y[i]-y[j]); 
         if (d< minDist) { 
             minDist=d; 
             index1=i; 
             index2=j; 
        } 
      } 
     return  minDist; 
} 

4. 源码

https://github.com/Marshmello11/Algorithm/tree/master/Experiment_5

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
最近点对问题是指在平面上给定N个点,求其中距离最近的两个点之间的距离。分治法是一种常用的最近点对问题算法分治法的基本思想是将问题成多个子问题,然后递归地决这些子问题,最后将子问题合并起来得到原问题。对于最近点对问题,我们可以采用以下的分治算法: 1. 将所有点按照横坐标从小到大排序,然后将它们划分为两部分,分别处理左右两个部分。 2. 对于左右两个部分,分别递归求最近点对距离。 3. 将左右两个部分中距离最近的点对的距离记为d。 4. 扫描所有横坐标在中间区域内的点,按照纵坐标从小到大排序。对于每个点,只需考虑它与纵坐标差不超过d的点之间的距离,因为这些点是可能成为最近点对的候选者。 5. 对于每个点,只需要考虑它与后面7个点之间的距离即可,因为如果有距离更近的点,它们之间的距离一定小于d。 6. 扫描完中间区域内的所有点后,最近点对的距离就是左右两个部分中的最小值和中间区域内的最小值中的较小值。 下面是该算法的伪代码: ``` function closest_pair(points): // 按照横坐标排序 sort(points, key=lambda p: p.x) // 递归终止条件 if len(points) <= 3: return brute_force(points) // 求左右两个部分的最近点对距离 mid = len(points) // 2 left_points = points[:mid] right_points = points[mid:] left_min_dist = closest_pair(left_points) right_min_dist = closest_pair(right_points) // 求中间区域的最近点对距离 min_dist = min(left_min_dist, right_min_dist) strip_points = [p for p in points if abs(p.x - points[mid].x) < min_dist] strip_points.sort(key=lambda p: p.y) for i in range(len(strip_points)): for j in range(i+1, min(i+8, len(strip_points))): dist = distance(strip_points[i], strip_points[j]) min_dist = min(min_dist, dist) return min_dist ``` 其中,brute_force是暴力求最近点对距离的函数,distance是计算两个点之间距离的函数。时间复杂度约为O(N log N)。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值