求最小点对主要是分治的思想,divide and qunquer
先将所有的点按照x(或y)排序,然后找中间轴,分别求轴两边的最小点对,以此递推。
然后找位于轴两侧的点中是否有点对距离更小
找到所有与中轴的距离小于当前最小距离的点,然后按照y(或x)排序,找这些点中是否有距离更小的点对。
一旦有点对的y坐标差大于最小距离,就可以break,以此减少时间复杂度。
附上代码:hdu 1007
#include<iostream>
#include<stdio.h>
#include<vector>
#include<algorithm>
#include<limits>
#include<math.h>
#define N 100000
using namespace std;
struct point{
double x;
double y;
};
point p[N + 10];
point po[N + 10];
double min(double a , double b){
return a < b? a:b;
}
double dis(point a,point b){
return (a.x-b.x)*(a.x-b.x) + (a.y-b.y)*(a.y-b.y);
}
bool cmp(const point &a, const point &b){
if(a.y<b.y || a.y==b.y && a.x<b.x){
return true;
}
return false;
}
bool comp(const point &a, const point &b){
return a.x<b.x;
}
double closestDistance(int start, int end){
double minDis = numeric_limits<double>::max();
if(end - start <= 2){
if(end - start == 2){
minDis = min( min( dis(p[start],p[start+1]), dis(p[start],p[end]) ), dis(p[start+1],p[end]) );
}
if(end - start == 1){
minDis = dis(p[start],p[end]);
}
return minDis;
}
int mid = (start+end) / 2;
double left = closestDistance(start,mid);
double right = closestDistance(mid+1,end);
minDis = min(left,right);
// cout<<"left "<<left<<" right "<<right<<endl;
int num = 0;
for(int i=start; i<=end; i++){
if((p[i].y-p[mid].y)*(p[i].y-p[mid].y) <= minDis){
po[num++] = p[i];
}
}
sort(po,po+num,comp);
for(int j=0; j<num; j++){
for(int k=j+1; k<num; k++){
if((po[j].x-po[k].x) * (po[j].x-po[k].x) >= minDis){
break;
}
minDis = min(minDis,dis(po[j],po[k]));
}
}
return minDis;
}
int main(){
int n;
while(scanf("%d",&n)!=EOF && n!=0){
for(int i = 0; i < n;i++){
scanf("%lf%lf",&p[i].x,&p[i].y);
}
sort(p,p+n,cmp);
double ans = closestDistance(0,n-1);
ans = sqrt(ans)/2;
printf("%.2lf\n",ans);
}
return 0;
}