hdu3007Buried memory(最小圆覆盖)
普通的暴力复杂度达到O(n^4),对于这题肯定是不行的。
解法:随机增量算法
参考http://www.2cto.com/kf/201208/149602.html
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仍旧是线性。于是难以置信的最小圆覆盖的复杂度变成了线性的。
1 #include <iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<algorithm> 5 #include<stdlib.h> 6 #include<vector> 7 #include<cmath> 8 #include<queue> 9 #include<set> 10 using namespace std; 11 #define N 505 12 #define LL long long 13 #define INF 0xfffffff 14 const double eps = 1e-8; 15 const double pi = acos(-1.0); 16 const double inf = ~0u>>2; 17 struct point 18 { 19 double x,y; 20 point(double x=0,double y = 0):x(x),y(y){} 21 }p[N]; 22 typedef point pointt ; 23 pointt operator -(point a,point b) 24 { 25 return point(a.x-b.x,a.y-b.y); 26 } 27 int dcmp(double x) 28 { 29 if(fabs(x)<eps) return 0; 30 return x<0?-1:1; 31 } 32 double dis(point a) 33 { 34 return sqrt(a.x*a.x+a.y*a.y); 35 } 36 point circumcenter(point a, point b, point c) 37 { //返回三角形的外心 38 point ret; 39 double a1 = b.x-a.x,b1 = b.y-a.y,c1 = (a1*a1+b1*b1)/2; 40 double a2 = c.x-a.x,b2 = c.y-a.y,c2 = (a2*a2+b2*b2)/2; 41 double d = a1*b2-a2*b1; 42 ret.x=a.x+(c1*b2-c2*b1)/d; 43 ret.y=a.y+(a1*c2-a2*c1)/d; 44 return ret; 45 } 46 void min_cover_circle(point p[],int n,point &c,double &r) 47 { 48 random_shuffle(p,p+n); 49 c = p[0],r = 0; 50 int i,j,g; 51 for(i = 1; i < n ;i++) 52 { 53 if(dcmp(dis(p[i]-c)-r)>0) 54 { 55 c = p[i]; 56 r = 0; 57 for(j = 0; j < i ; j++) 58 { 59 if(dcmp(dis(p[j]-c)-r)>0) 60 { 61 c = point((p[i].x+p[j].x)/2,(p[i].y+p[j].y)/2); 62 r = dis(p[j]-c); 63 for(g = 0 ; g < j; g++) 64 if(dcmp(dis(p[g]-c)-r)>0) 65 { 66 c = circumcenter(p[i],p[j],p[g]); 67 r = dis(p[i]-c); 68 } 69 } 70 } 71 } 72 } 73 } 74 int main() 75 { 76 int n,i; 77 while(scanf("%d",&n)&&n) 78 { 79 for(i = 0; i < n; i++) 80 scanf("%lf%lf",&p[i].x,&p[i].y); 81 point c; 82 double r; 83 min_cover_circle(p,n,c,r); 84 printf("%.2f %.2f %.2f\n",c.x,c.y,r); 85 } 86 return 0; 87 }
1 #include <iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<algorithm> 5 #include<stdlib.h> 6 #include<vector> 7 #include<cmath> 8 #include<queue> 9 #include<set> 10 using namespace std; 11 #define N 505 12 #define LL long long 13 #define INF 0xfffffff 14 const double eps = 1e-8; 15 const double pi = acos(-1.0); 16 const double inf = ~0u>>2; 17 struct point 18 { 19 double x,y; 20 point(double x=0,double y = 0):x(x),y(y){} 21 }p[N]; 22 typedef point pointt ; 23 pointt operator -(point a,point b) 24 { 25 return point(a.x-b.x,a.y-b.y); 26 } 27 int dcmp(double x) 28 { 29 if(fabs(x)<eps) return 0; 30 return x<0?-1:1; 31 } 32 double dis(point a) 33 { 34 return sqrt(a.x*a.x+a.y*a.y); 35 } 36 point circumcenter(point a, point b, point c) 37 { //返回三角形的外心 38 point ret; 39 double a1 = b.x-a.x,b1 = b.y-a.y,c1 = (a1*a1+b1*b1)/2; 40 double a2 = c.x-a.x,b2 = c.y-a.y,c2 = (a2*a2+b2*b2)/2; 41 double d = a1*b2-a2*b1; 42 ret.x=a.x+(c1*b2-c2*b1)/d; 43 ret.y=a.y+(a1*c2-a2*c1)/d; 44 return ret; 45 } 46 void min_cover_circle(point p[],int n,point &c,double &r) 47 { 48 random_shuffle(p,p+n); 49 c = p[0],r = 0; 50 int i,j,g; 51 for(i = 1; i < n ;i++) 52 { 53 if(dcmp(dis(p[i]-c)-r)>0) 54 { 55 c = p[i]; 56 r = 0; 57 for(j = 0; j < i ; j++) 58 { 59 if(dcmp(dis(p[j]-c)-r)>0) 60 { 61 c = point((p[i].x+p[j].x)/2,(p[i].y+p[j].y)/2); 62 r = dis(p[j]-c); 63 for(g = 0 ; g < j; g++) 64 if(dcmp(dis(p[g]-c)-r)>0) 65 { 66 c = circumcenter(p[i],p[j],p[g]); 67 r = dis(p[i]-c); 68 } 69 } 70 } 71 } 72 } 73 } 74 int main() 75 { 76 int n,i; 77 while(scanf("%d",&n)&&n) 78 { 79 for(i = 0; i < n; i++) 80 scanf("%lf%lf",&p[i].x,&p[i].y); 81 point c; 82 double r; 83 min_cover_circle(p,n,c,r); 84 printf("%.2f %.2f %.2f\n",c.x,c.y,r); 85 } 86 return 0; 87 }