您的位置:首页 > 其它

分治法求最接近点对问题

2016-04-16 23:36 302 查看
问题描述:在点集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;
}


“`
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: