分治法求最接近点对问题

分治算法 专栏收录该内容
2 篇文章 0 订阅

问题描述:在点集P中,找出这样的一对点,使得他们之间的距离在点集P中每两两所组成的所有点对中距离最小。(当然,这样的点对可能不止一组,但我们只要求输出一组即可。)
为了便于理解,我们循序渐进的来讨论这个问题,从中我们也慢慢体会分治算法的精妙之处。

首先说说一维情况:
即假设这些点都位于一条直线上(x坐标轴上),采用分治法思想,考虑将所给的n个点的集合S分成2个子集S1和S2,每个子集中约有n/2个点,然后在每个子集中递归地求其最接近的点对。在这里,一个关键的问题是如何实现分治法中的合并步骤,即由S1和S2的最接近点对,如何求得原集合S中的最接近点对,因为S1和S2的最接近点对未必就是S的最接近点对。如果组成S的最接近点对的2个点都在S1中或都在S2中,则问题很容易解决。如果这2个点分别在S1和S2中呢?此时我们可能就会想到按照x坐标的顺序从左到右对他们进行排序了,排序之后,如果说这2个点分别在S1和S2中,那么必定是S1的最后一个点(S1中x坐标最大的)和S2中的第一个点(S2中x坐标最小的)。依此思路给出如下代码:

#include <algorithm>
#include <cmath>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <ctime>
#include <ctype.h>
#include <iostream>
#include <map>
#include <queue>
#include <set>
#include <stack>
#include <string>
#include <vector>
#define eps 1e-8
#define INF 0x7fffffff
#define PI acos(-1.0)
#define seed 31//131,1313
typedef long long LL;
typedef unsigned long long ULL;
using namespace std;
const int maxn=100005;
struct Point{
  double x;
}p[maxn];

int a[maxn];
int cmpx(Point a,Point b){
  return a.x<b.x;
}
inline double dis(Point a,Point b){
   if(a.x>b.x) return a.x-b.x;
   else return b.x-a.x;
}

double closest(int low,int high){
  if(low+1==high)  //只有两个点
    return dis(p[low],p[high]);
  if(low+2==high)  //只有三个点
    return min(dis(p[low],p[high]),min(dis(p[low],p[low+1]),dis(p[low+1],p[high])));
  int mid=(low+high)/2; //求中点即左右子集的分界线
  double d=min(closest(low,mid),closest(mid+1,high));
  d=min(d,dis(p[mid],p[mid+1])); //最后一步,合并
  return d;
}
int main()
{
    int n;
    while(scanf("%d",&n)!=EOF){
        for(int i=0;i<n;i++)
            scanf("%lf",&p[i].x);
        sort(p,p+n,cmpx);
        printf("%.2lf\n",closest(0 , n-1));//最近点对间的距离
    }
    return 0;
}

“`

  • 0
    点赞
  • 0
    评论
  • 4
    收藏
  • 一键三连
    一键三连
  • 扫一扫,分享海报

©️2021 CSDN 皮肤主题: 大白 设计师:CSDN官方博客 返回首页
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值