题目链接:https://vjudge.net/problem/HDU-1007
题意:给定n个点,求平面距离最小点对的距离除2。
思路:分治求最小点对,对区间[l,r]递归求[l,mid]和[mid+1,r]的最小点对,取两者中的小者设为d。然后处理一个点在左区间,一个点在右区间的情况。一个点P在左区间,如果使它与右区间Q一个点距离小于d的话,那么P到mid的距离一定小于的,Q也是,且P和Q的纵坐标之差小于d。可以证明这样的Q点最多6个。那么我们把符合到mid距离小于d的点按y排序后,遍历一遍更新d即可。
AC代码:
#include<cstdio> #include<cmath> #include<cstdlib> #include<algorithm> using namespace std; const int maxn=1e5+5; int n,id[maxn],cnt; const double inf=1e30; struct node{ double x,y; }pt[maxn]; bool operator < (const node& a,const node& b){ if(a.x==b.x) return a.y<b.y; return a.x<b.x; } bool cmp(int a,int b){ return pt[a].y<pt[b].y; } double dist(const node& a,const node& b){ return sqrt((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y)); } double fenzhi(int l,int r){ double d=inf; if(l==r) return d; if(l+1==r) return dist(pt[l],pt[r]); int mid=(l+r)>>1; d=min(fenzhi(l,mid),fenzhi(mid+1,r)); cnt=0; int t1,t2,l1=l,r1=mid,mid1; while(l1<=r1){ mid1=(l1+r1)>>1; if(pt[mid].x-pt[mid1].x<d) r1=mid1-1; else l1=mid1+1; } t1=l1; l1=mid+1,r1=r; while(l1<=r1){ mid1=(l1+r1)>>1; if(pt[mid1].x-pt[mid].x<d) l1=mid1+1; else r1=mid1-1; } t2=r1; for(int i=t1;i<=t2;++i) id[++cnt]=i; sort(id+1,id+cnt+1,cmp); for(int i=1;i<cnt;++i) for(int j=i+1;j<=cnt&&(pt[id[j]].y-pt[id[i]].y)<d;++j) d=min(d,dist(pt[id[i]],pt[id[j]])); return d; } int main(){ while(scanf("%d",&n),n){ for(int i=1;i<=n;++i) scanf("%lf%lf",&pt[i].x,&pt[i].y); sort(pt+1,pt+n+1); printf("%.2f ",fenzhi(1,n)/2); } return 0; }