给出二维平面上的n个点,求其中最近的两个点的距离的一半。
输入包含多组数据,每组数据第一行为n,表示点的个数;接下来n行,每行一个点的坐标。当n为0时表示输入结束,每组数据输出一行,为最近的两个点的距离的一半。
Sample Input
2
0 0
1 1
2
1 1
1 1
3
-1.5 0
0 0
0 1.5
0
Sample Output
0.71
0.00
0.75
题解:
需要在所有点中寻找最近的两个点对,这时候需要借助二分思想。
先从一维进行分析,
使用快排先将x轴排序(从小到大),递归的求左边和右边最小距离的点对将其合并,并不断判断并且选取左边和右边最小距离点对的距离。
递归求出S1中的最小点对{p1,p2},递归求出S2中最小点对{q1,q2}
判断d = min{|p1-p2|,|q1-q2|}
合并后还需判断{p3,q3}是否比d小,这个时候应该遍历出(m-d,m+d)中所有的点,判断是否有比d小的点。
时间复杂度为:O(nlogn)。
二维情况下,首先根据一维的方法将x轴,使用二分进行判断左右边点对最小值min,选出左右中点对距离最小值min,接下来将y轴进行排序,寻找被选取每个点与其他点满足 (y该点)∈[y-min,y+min],并且判断是否比min小,若小选取该点对距离。(此处最多出现六个满足的点 --鸽巢原理,but 其实使用 (y该点) 做判断也是一样的)。
#include <iostream>
#include <algorithm>
#include <cmath>
#include <cstdio>
using namespace std;
struct Note{
double x,y;
};
Note Point[100002];
int tempPoint[100002];
bool compx(Note a,Note b){return a.x<b.x;}//x轴排序
bool compy(int a,int b){return Point[a].y<Point[b].y;}//y轴排序
double poww(Note a,Note b){return sqrt((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y));}
double min(double a,double b){return a<b?a:b;}
double compute(int start,int endd){
if(endd - start == 1){
return poww(Point[start],Point[endd]);//剩两个点的时候
}
if(endd - start == 2){
return min(poww(Point[start],Point[endd]),min(poww(Point[start+1],Point[start]),poww(Point[start+1],Point[endd])));
}//剩三个点的时候,这样做是为了减少复杂度
int mid = (start+endd)>>1;//取中值
double l_min = compute(start,mid);//递归求左边对点距离最小值
double r_min = compute(mid+1,endd);//递归求右边对点距离最小值
double minmin = l_min>r_min?r_min:l_min;
int cou = 0;
for(int i = start;i <= endd;i ++){
if(Point[i].x >= Point[mid].x - minmin&&Point[i].x <= Point[mid].x + minmin){
tempPoint[cou++] = i;//寻找中点两边小于min的的点,有可能有些点对距离小,且跨越中点
}
}
sort(tempPoint,tempPoint+cou,compy);//对y轴排序
for(int i = 0;i < cou;i ++){//被选取的y轴的点对进行判断
int k = 0;
for(int j = i + 1;j < cou;j++){
k ++;
if(Point[tempPoint[j]].y - Point[tempPoint[i]].y > minmin){
break;
}
double temp = poww(Point[tempPoint[i]],Point[tempPoint[j]]);
minmin = min(temp ,minmin);
if(k == 6) break;
}
}
return minmin;
}
int main(){
int n;
while(scanf("%d",&n)!=EOF){
if(!n) break;
for(int i = 0;i < n;i ++){
scanf("%lf %lf",&Point[i].x,&Point[i].y);
}
sort(Point,Point+n,compx);
double d = compute(0,n-1);
printf("%.2lf\n",d);
}
return 0;
}