题目地址:hdu:点击打开链接
ZOJ:点击打开链接
该代码在ZOJ能AC,但hdu就不行,不过可以作为一个经典案例分析:
#include<stdio.h>
#include<math.h>
#include <stdlib.h>
/*结构体尽量写成全局变量*/
struct point{
double x,y;
}node[100005];
int tmp[100005];
double min(double a,double b){
if(a<=b)
return a;
if(a>b)
return b;
}
/*结构体的快排,注意返回值是int,如果直接两double相减会出错*/
int cmpx( const void *a , const void *b ){
struct point *c = (struct point *)a;
struct point *d = (struct point *)b;
if(c->x != d->x) return c->x < d->x;
else return d->y < c->y;
}
/*传的数组作为下标时可以引入中间变量,只要控制传回的-1,0,1正确即可*/
int cmp( const void *a ,const void *b){
double temp = ((struct point*)a)->y-((struct point*)b)->y;
if(temp>0)
return 1;
else if(temp==0)
return 0;
else
return -1;
}
double dist(struct point a,struct point b){
double dis=(a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y);
return sqrt(dis);
}
double min_dist(int left,int right){
int i,j;
double d=1e100;
/*分的只有一个点时肯定不能算进去,算作无穷大*/
if(left==right)
return d;
/*两个点时传回距离*/
else if(left+1==right)
return dist(node[left],node[right]);
int mid=(left+right)/2;
d=min(min_dist(left,mid),min_dist(mid+1,right));
/*搞完上面的才能搞下面的,也就是说多次递归后直到计算完d才进行下面的
而计算中间矩形区域最小值是不需要递归的*/
int pos=0;
/*一个O(n)复杂度的循环真的不算什么,O(n)的循环尽管用就行*/
for(i=left;i<=right;i++){
if(fabs(node[i].x-node[mid].x)<=d) /*把以mid为中线,左右两边距离为d的矩形里的点都搞进来*/
tmp[pos++]=i; /*记录有几个点和其位置*/
}
qsort(tmp,pos,sizeof(tmp[0]),cmp); /*把记录的这几个数按y排了*/
for(i=0;i<pos;i++)
for(j=i+1;j<pos&&node[tmp[j]].y-node[tmp[i]].y<=d;j++){ /*把y轴上的距离判断一下,主要是若单看y上的投影都比d大,距离肯定更大了*/
double dd=dist(node[tmp[i]],node[tmp[j]]); /*其实每个点只要和对面判断6次就行了。符合条件比较下距离*/
d=min(d,dd);
}
return d;
}
int main(){
int i,j,n,a,b;
while(scanf("%d",&n)&&n){
for(i=0;i<n;i++)
scanf("%lf%lf",&node[i].x,&node[i].y);
/*超时的原因可能是快排最坏时间复杂度太高*/
qsort(node,n,sizeof(node[0]),cmpx);
double ans=min_dist(0,n-1)/2.0;
printf("%.2lf\n",ans);
}
return 0;
}