http://acm.hdu.edu.cn/showproblem.php?pid=1007
这题需要注意的有两点:
一:题目本身,做的思路是分治,像快速排序那样,把所有的点分成差不多的两段,然后再分……直至只剩2个或三个,那样就可以直接算了。
算法流程:
1:进入递归过程:如果是该段点数不大于三,那么就可以直接算了,否则用分治法递归解决
2:将大于四的这堆点分成两部分,得到最小的距离d。但这个距离还不能确定是最小的min,因为有可能一点p在左边,一点q在右边,而他们的距离有可能比d还小,是真正的min
3:将这堆实现按x排好序的点分成两部分,左边标志L,右边标志R,两个值不同。遍历左边的,找到所有距离中间这个点p[middle].x不超过d的,存在temp里
再遍历右边的,找到同样符合条件的点存在temp里。
4.遍历temp,穷举符合条件的点,不断更新min的值,这样的点不超过8过,《编程之美》里有解说。
5:返回min
二:贡献N次wa后才发觉可能是排序有问题,早知道就手搓了
ac代码
#include<stdio.h> #include<math.h> #include<stdlib.h> #define L -1 #define R 1 typedef struct node { int flag;//标志在左边还是右边 double x,y; }point; point p[1000100],temp[1000100];//point存储点信息,minx存储x-d~x+d的点,miny则存储y-d~y+d的点 int cmpx(const void *a, const void *b) { point *pa = (point *) a; point *pb = (point *) b; if (pa->x > pb->x) return 1; else if (pa->x < pb->x) return -1; else return 0; } int cmpy(const void *a, const void *b) { int *pa = (int *) a; int *pb = (int *) b; if (temp[*pa].y > temp[*pb].y) return 1; else if (temp[*pa].y < temp[*pb].y) return -1; else return 0; } double minp(double a,double b) { return a>b?b:a; } double distance(point a,point b) { return sqrt(pow(a.x-b.x,2.0)+pow(a.y-b.y,2.0)); } double getmindistance(int left,int right) { double temp1,temp2,temp3,mindistance; int j=0,k=0,i,middle; if(left==right) return 0; else if(left+1==right) return distance(p[left],p[right]);//两个点 else if(left+2==right) { temp1=distance(p[left],p[left+1]); temp2=distance(p[left+1],p[right]); temp3=distance(p[left],p[right]); return minp(minp(temp1,temp2),temp3);//三个点 } else { middle=(left+right)/2; temp1=getmindistance(left,middle); temp2=getmindistance(middle+1,right); mindistance=minp(temp1,temp2); for(i=left;i<=middle;i++) { if(p[middle].x-p[i].x<=mindistance) { temp[j].flag=L; temp[j].x=p[i].x; temp[j].y=p[i].y; j++; } } for(;i<=right;i++) { if(p[i].x-p[middle].x<=mindistance) { temp[j].flag=R; temp[j].x=p[i].x; temp[j].y=p[i].y; j++; } } //qsort(temp,j,sizeof(temp[0]),cmpy);这里的排序是按另一种做法时才用到的 for(i=0;i<j;i++) for(k=1;(k<8)&&(i+k<j);k++) { if(temp[i].flag!=temp[i+k].flag) mindistance=minp(distance(temp[i],temp[i+k]),mindistance); } return mindistance; } } int main() { int n,i; double answer; while(scanf("%d",&n),n) { for(i=0;i<n;i++) { scanf("%lf%lf",&p[i].x,&p[i].y); p[i].flag=0; } qsort(p,n,sizeof(p[0]),cmpx);//先按x排序 answer=getmindistance(0,n-1); printf("%.2lf ",answer/2.0);//题目要求的是半径 } return 0; }