#include "stdio.h"
#include "stdlib.h"
#include "math.h"
#define INF 100000000
#define N 100000
struct
{
double x;
double y;
}point[N];
int temp[N];
int cmpy(const void * y1, const void * y2) //根据y坐标进行排序
{
if(*(double *)y1 < *(double *)y2)
return 1;
return 0;
}
int cmpxy(const void *index1, const void *index2)
{
if(fabs(point[*(int *)index1].x - point[*(int *)index2].x) > 1e-3) //如果x坐标不同
if(point[*(int *)index1].x < point[*(int *)index2].x) //根据x坐标排序
return 1;
else//x坐标相同的情况下,根据y坐标排序
{
if(point[*(int *)index1].y < point[*(int *)index2].y)
return 1;
}
return 0;
}
double dist(int index1, int index2) //计算点index1和点index2的距离
{
double dx = fabs(point[index1].x - point[index2].x);
double dy = fabs(point[index1].y - point[index2].y);
double d = dx*dx + dy*dy;
return sqrt(d);
}
double min(double a, double b)
{
return a<b?a:b;
}
double cloest_pair(int left, int right)
//返回点区间上最近两点间的距离,
//left为区间最左边的点,right为最右边的点
{
double d = INF;
if(right == left) //如果只有一个点
return d;
else if(right == left+1) //如果只有两个点
return dist(left, right); //如果有三个及以上的点
else
{
int mid = (left+right)>>1; //取区间中点
double d1 = cloest_pair(left, mid); //d1=左半区间最近点距离
double d2 = cloest_pair(mid+1, right); //d1=右半区间最近点距离
d = min(d1, d2);
int i, j, k=0;
//以左半区间和右半区间的垂直分割线为中心,分离出宽度为d的区间
for(i=left; i<=right; i++)
{
if(fabs(point[i].x-point[mid].x)<=d/2)
temp[k++] = i;
}
qsort(temp, k, sizeof(int), cmpy); //将距离d之内的点按y坐标排序
//对y坐标线性扫描
for(i=0; i<=k; i++)
{ //对于x坐标在宽度为d的区间内的每个点,y坐标在宽度为2d之内
for(j=i+1; j<k && fabs(point[temp[j]].y-point[temp[i]].y)<d; j++)
{
double d3 = dist(temp[i], temp[j]);
if(d3<d)
d = d3; //更新最短距离
}
}
}
return d;
}
int main()
{
int len;
int i, k;
printf("输入点对个数:");
scanf("%d", &len);
printf("输入各点:\n");
for(i=0; i<len; i++)
{
printf("x=");
scanf("%lf", &point[i].x);
printf("y=");
scanf("%lf", &point[i].y);
}
qsort(point, len, sizeof(point[0]), cmpxy);
double d = cloest_pair(0, len-1);
printf("最短距离为:%lf\n", d);
return 0;
}
最近点对
最新推荐文章于 2023-12-26 12:05:08 发布