标签:否则 nes points ret find content hand esc pac
给你平面上n个点,让你找最近的2个点的距离的一半
经典的分治问题,我们现将点按照x坐标排序,先处理前一半的答案,再处理后一半的答案,两个取最小ans
现在还没完呢,万一一个点在左半边另一个点在右半边呢?这样我们就要更新答案了.我们注意到这样的点肯定满足到中心的点的距离不超过ans
我们暴力搞出这些点,这些点是有可能来更新ans的,我们是不是要将这些点n^2算距离更新呢?这样显然是超时的
我们将这些点按y坐标排序,我们对于第1个点开始求它与第2~cnt个点的y坐标的差值,一旦这个差值大于ans就不用再去比较后面的点了,我们再从第2个点求它与第3~cnt个点的y坐标差,以此类推
这样及时的break就优化了......
谁信啊!!!!其实这涉及到一个点周围能够更新ans的点最多有6个,否则上面ans就不是答案了
代码如下:
1 #include <bits/stdc++.h> 2 3 using namespace std; 4 const int maxn = 1100000; 5 struct point 6 { 7 double x,y; 8 }p[maxn]; 9 int a[maxn]; 10 double dis (point q1,point q2) 11 { 12 return sqrt((q1.x-q2.x)*(q1.x-q2.x)+(q1.y-q2.y)*(q1.y-q2.y)); 13 } 14 bool cmpx (point q1,point q2) 15 { 16 return q1.x<q2.x; 17 } 18 bool cmpy (int q1,int q2) 19 { 20 return p[q1].y<p[q2].y; 21 } 22 int n; 23 double calc (int l,int r) 24 { 25 if (r==l+1) 26 return dis(p[l],p[r]); 27 else if (r==l+2) 28 return min(dis(p[l],p[l+1]),min(dis(p[l+1],p[r]),dis(p[l],p[r]))); 29 else{ 30 int mid = (l+r)/2; 31 double ans = min(calc(l,mid),calc(mid+1,r)); 32 int cnt = 0; 33 for (int i=l;i<=r;++i){ 34 if (p[i].x>=p[mid].x-ans&&p[i].x<=p[mid].x+ans) 35 a[cnt++]=i; 36 } 37 sort(a,a+cnt,cmpy); 38 for (int i=0;i<cnt;++i){ 39 for (int j=i+1;j<cnt;++j){ 40 if (p[a[j]].y-p[a[i]].y>=ans) break; 41 else{ 42 ans = min(ans,dis(p[a[i]],p[a[j]])); 43 } 44 } 45 } 46 return ans; 47 } 48 } 49 int main() 50 { 51 //freopen("de.txt","r",stdin); 52 while (~scanf("%d",&n)){ 53 if (n==0) break; 54 for (int i=0;i<n;++i){ 55 scanf("%lf%lf",&p[i].x,&p[i].y); 56 } 57 sort(p,p+n,cmpx); 58 double ans = calc(0,n-1); 59 printf("%.2f\n",ans/2); 60 } 61 return 0; 62 }
精髓就是通过不断二分从指数上将复杂度降下来
hdu 1007 Quoit Design (经典分治 求最近点对)
标签:否则 nes points ret find content hand esc pac
原文地址:http://www.cnblogs.com/agenthtb/p/7533414.html