POJ 3714-Raid解题报告
二维最近点对问题,关于这个问题网上和算法导论上都由详细的介绍http://hi.baidu.com/bananas122/item/fbc7a2b6d766bf6e254b09e4
这个解释的挺好,并且还有计算,其他的就是代码实现的问题,另外这个题要加一个标志位,就没什么特殊的了
View Code
1 #include<iostream> 2 #include<cstring> 3 #include<cstdio> 4 #include<cstdlib> 5 #include<cmath> 6 #include<algorithm> 7 #define N 200005 8 #define min(a,b) ((a)<(b)?(a):(b)) 9 #define inf 1e50 10 using namespace std; 11 struct point 12 { 13 double x,y; 14 int flag; 15 }; 16 point p[N]; 17 point tmp1[N]; 18 point tmp2[N]; 19 bool cmp(point a,point b) 20 { 21 if(a.x!=b.x) 22 return a.x<b.x; 23 return a.y<b.y; 24 } 25 double dis(point p1,point p2) 26 { 27 if(p1.flag==p2.flag) 28 return inf; 29 return sqrt(((p1.x-p2.x)*(p1.x-p2.x)+(p1.y-p2.y)*(p1.y-p2.y))); 30 } 31 double mindis(int l,int r) 32 { 33 double d=inf; 34 if(l==r) 35 return d; 36 if(l+1==r) 37 return dis(p[l],p[r]); 38 int mid=(l+r)>>1; 39 double d1=mindis(l,mid);//分治,这里感觉有些像线段树 40 double d2=mindis(mid+1,r); 41 d=min(d1,d2); 42 int i,j,k; 43 int cnt1,cnt2; 44 cnt1=cnt2=0; 45 for(i=mid;i>=l;i--)//找两边的点 46 { 47 if(p[mid].x-p[i].x<d) 48 tmp1[cnt1++]=p[i]; 49 } 50 for(i=mid+1;i<=r;i++) 51 { 52 if(p[i].x-p[mid].x<d) 53 tmp2[cnt2++]=p[i]; 54 } 55 for(i=0;i<cnt1;i++) 56 for(j=0;j<cnt2;j++) 57 { 58 d1=dis(tmp1[i],tmp2[j]); 59 if(d1<d) 60 d=d1; 61 } 62 return d; 63 } 64 int main() 65 { 66 int n,i,j,k; 67 int T; 68 scanf("%d",&T); 69 while(T--) 70 { 71 scanf("%d",&n); 72 for(i=0;i<n;i++) 73 { 74 scanf("%lf%lf",&p[i].x,&p[i].y); 75 p[i].flag=0; 76 } 77 for(i=n;i<2*n;i++) 78 { 79 scanf("%lf%lf",&p[i].x,&p[i].y); 80 p[i].flag=1; 81 } 82 n*=2; 83 sort(p,p+n,cmp);//一定要用sort 84 printf("%.3lf\n",mindis(0,n-1)); 85 } 86 return 0; 87 }