最小圆覆盖。神奇的随机算法。当点以随机的顺序加入时期望复杂度是线性的。
algorithm:
A、令Ci表示为前i个点的最小覆盖圆。当加入新点pi时如果pi不在Ci-1里那么pi必定在Ci的边界上。 B、再从新考虑这样一个问题,Ci为前i个点最小覆盖圆且p在Ci的的边界上!同理加入新点pi时如果p i不在Ci-1里那么pi必定在Ci的边界上。这时我们就包含了两个点在这个最小圆的边界上。 C、再从新考虑这样一个问题,Ci为前i个点最小覆盖圆且有两个确定点再边界上!此时先让 O(N)的方法能够判定出最小圆。 analysis: 现在来分析为什么是线性的。 C是线性的这是显然的。 B<-C的过程中。考虑pi 他在园内的概率为 (i-1)/i 。在圆外的概率为 1/i 所以加入pi的期望复杂度为:(1-i)/i*O(1) +(1/i)*O(i) {前者在园内那么不进入C,只用了O(1)。后者进入C用了O(i)的时间}这样分析出来,复杂度实际上仍旧 是线性的。 A<-B的过程中。考虑方法相同,这样A<-B仍旧是线性。于是难以置信的最小圆覆盖的复杂度变成了线性的。 struct Point { double x,y; } point[M]; double Pow(double x) { return x*x; } double dist(Point a,Point b) { return sqrt(Pow(a.x-b.x)+Pow(a.y-b.y)); } void Circle(Point P0,Point P1,Point P2,Point &o) { double a1=P1.x-P0.x,b1=P1.y-P0.y,c1=(Pow(a1)+Pow(b1))/2; double a2=P2.x-P0.x,b2=P2.y-P0.y,c2=(Pow(a2)+Pow(b2))/2; double d=a1*b2-a2*b1; o.x = P0.x + (c1*b2-c2*b1)/d; o.y = P0.y + (a1*c2-a2*c1)/d; } void MinCircle(Point point[],Point &o,double &r,int n)//点集 圆心存于o,半径r ,n点的个数 { random_shuffle(point,point+n); int i,j,k; o = point[0]; for(r = 0,i = 1; i < n; ++i) { if(dist(point[i],o) <= r)continue; o = point[i]; for(r = j = 0; j < i; ++j) { if(dist(point[j],o) <= r)continue; o.x = (point[i].x+point[j].x)/2; o.y = (point[i].y+point[j].y)/2; r = dist(o,point[i]); for(k = 0; k < j; ++k) { if(dist(point[k],o) Circle(point[i],point[j],point[k],o); r = dist(o,point[i]); } } } } |
最小圆覆盖
最新推荐文章于 2021-05-22 20:41:24 发布