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
",c.x,c.y,r);
85     }
86     return 0;
87 }
View Code
 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
",c.x,c.y,r);
85     }
86     return 0;
87 }
View Code
原文地址:https://www.cnblogs.com/shangyu/p/3891061.html