一、问题描述
给定平面上n个点,找其中一对点,使得在n个点组成的所有点对中,该点对间的距离最小。
二、算法描述(伪代码)
double cpair(Point p[], int left , int right)
{
n=p.size();
if(n<2)
return 0x3f3f3f3f;
1、
int mid=(left+right)/2;
构造p1,p2;
p1={point∈p | point.x<=m}
p2={point∈p | point.x>m}
2、
double d1=cpair(p,left,m);
double d2=cpair(p,m,right);
double d=min(d1,d2);
3、
所有|p[i].x-p[mid].x|<d 的点加入到stripe[]中
4、
stripe[]中的点按y的大小排序,检查stripe[]中的点与其在d范围内的所有点(最多六个)的距离是否比d小,若小于d,则赋值
return d
}
三、算法实现
#include <stdio.h>
#include <stdlib.h>
#include <float.h>
#include <string.h>
#include <math.h>
#include <algorithm>
#include <iostream>
#define min(a,b) (a<b?a:b)
using namespace std;
int n;
typedef struct point{
double x;
double y;
}point;
point p[100];
point re[2];
double mm=0x3f3f3f3f;
bool comp(point &a,point &b)
{
return a.x<b.x;
}
bool compy(point &a,point &b)
{
return a.y<b.y;
}
void input()
{
double temp;
int i;
memset(p,0,sizeof(point)*100);
memset(re,0,sizeof(point)*2);
scanf("%d",&n);
printf("origin point pairs : \n");
for(i=0;i<n;i++)
{
temp=rand()%100*0.1;
p[i].x=temp;
temp=rand()%100*0.1;
p[i].y=temp;
printf("(%f,%f) ",p[i].x,p[i].y);
}
printf("\n");
printf("sorted point pairs :\n");
sort(p,p+n,comp);//时间复杂度为O(nlgn)
for(i=0;i<n;i++)
printf("(%f,%f) ",p[i].x,p[i].y);
printf("\n");
}
double distance_x(point a,point b)
{
return abs(a.x-b.x);
}
double distance_y(point a,point b)
{
return abs(a.y-b.y);
}
double dist(point a,point b)
{
return sqrt(distance_x(a,b)*distance_x(a,b)+distance_y(a,b)*distance_y(a,b));
}
double bruteforce(point p[],int left,int num)
{
int i,j;
double d=0x3f3f3f3f;
double temp;
for(i=left;i<num;i++)
{
for(j=i+1;j<num;j++)
{
temp=dist(p[i],p[j]);
if(temp<d)
{
d=temp;
re[0].x=p[i].x;
re[0].y=p[i].y;
re[1].x=p[j].x;
re[1].y=p[j].y;
}
}
}
return d;
}
double stripemin(point stripe[],int j,double d)
{
int i,k;
double minstripe=d;
sort(stripe,stripe+j,compy);
for(i=0;i<j;i++)
for(k=i+1;k<j&&(stripe[k].y-stripe[i].y)<d;k++)
{
if(dist(stripe[i],stripe[k])<minstripe)
{
minstripe=dist(stripe[i],stripe[k]);
re[0].x=stripe[i].x;
re[0].y=stripe[i].y;
re[1].x=stripe[k].x;
re[1].y=stripe[k].y;
}
}
return minstripe;
}
double cpair(point p[],int left,int num)
{
if(left<num)
{
int i;
int j=0;
double d1;
double d2;
double d;
if((num-left)==1)
return mm;
//else if((num-left)<4)
//return bruteforce(p,left,num);
int mid=(left+num)/2;
d1=cpair(p,left,mid);//from p[0]->p[mid-1] the number is mid
d2=cpair(p,mid,num);
d=min(d1,d2);
point *stripe=new point[n];
for(i=0;i<n;i++)
{
if(abs(p[i].x-p[mid].x)<d)
{
stripe[j]=p[i];
j++;
}
}
double temp=stripemin(stripe,j,d);
return min(d,temp);
}
else
return mm;
}
int main()
{
double result;
input();
result=bruteforce(p,0,n);
printf("bruteforce:the distance between (%f,%f) and (%f,%f) is %f\n",re[0].x,re[0].y,re[1].x,re[1].y,result);
result=cpair(p,0,n);
printf("cpair:the distance between (%f,%f) and (%f,%f) is %f\n",re[0].x,re[0].y,re[1].x,re[1].y,result);
return 0;
}
四、结果