最小覆盖圆
给出一堆点,求一个面积(半径)最小的圆,使得所有点都在它的内部或边界上.
随机增量法是这样的....
先随机打乱点的顺序......
然后,我们假设已经得到了点 $1,2,...,i$ 的最小覆盖圆,我们要求出点 $1,2,...,i,i+1$ 的最小覆盖圆.
怎么做? 考虑点 $i+1$ ,分两种情况:
1.如果点 $i+1$ 在点 $1,2,...,i$ 的最小覆盖圆里面或边界上,那么点 $1,2,...,i,i+1$ 的最小覆盖圆就是点 $1,2,...,i$ 的最小覆盖圆.
证明:
假设点 $1,2,...,i,i+1$ 的最小覆盖圆比点 $1,2,...,i$ 的最小覆盖圆小. 这意味着,我们可以用点 $1,2,...,i,i+1$ 的最小覆盖圆来覆盖点 $1,2,...,i$ ,因此我们找到了一个新的圆,它覆盖了点 $1,2,..,i$ 比 $1,2,...,i$ 的最小覆盖圆还要小.显然矛盾.
结合最小覆盖圆的唯一性可得出结论.
上述证明说明了,最小覆盖圆在我们依次添加点的过程中,面积(半径)一定单调不减的.
2.如果点 $i+1$ 在点 $1,2,...,i$ 的最小覆盖圆外,那么点 $i+1$ 一定在点 $1,2,...,i,i+1$ 的最小覆盖圆的边界上.
不会证!哪位神犇前来拯救我QAQ
有了这个性质以后,我们就可以按顺序来做"三点确定一个圆"的事情=.=
现在我们知道了点 $i+1$ 必定会在边界上. 那么我们再用一次这个方法:
假设我们已经得到了点 $1,2,...,j$ 的过点 $i+1$ 的最小覆盖圆. 现在我们要求点 $1,2,...,j,j+1$ 的,过点 $i+1$ 的最小覆盖圆. 如果点 $j+1$ 已经在那个最小覆盖圆里面,根据情况1可以将这个点忽略.如果不在,再用一次这个方法:
假设我们已经得到了点 $1,2,...,k$ 的,过两个点 $j+1,i+1$ 的最小覆盖圆. 现在我们要求点 $1,2,...,k,k+1$ 的,过点 $j+1,i+1$ 的最小覆盖圆. 如果点 $k+1$ 已经在那个最小覆盖圆里面,根据情况1可以将这个点忽略.如果不在,直接求三个点 $k+1,j+1,i+1$ 对应的外接圆.
于是我们就得到了一个覆盖了点 $1,2,...,k$ 的,经过点 $j+1,i+1$ 的最小覆盖圆. 当我们的指针 $k$ 扫完 $1,2,...,j$ 的时候,我们就求出了覆盖点 $1,2,...,j,j+1$ 的,经过点 $i+1$ 的最小覆盖圆. 当我们的指针 $j$ 扫完 $1,2,...,i$ 的时候,我们就求出了点 $1,2,...,i,i+1$ 的最小覆盖圆.
代码非常的暴力,把点集随机打乱以后就可以 $O(n)$ 了...
另外怎么证明,最小覆盖圆只能有一个?
AC BZOJ 2823 裸的最小覆盖圆
1 #include <cstdio>
2 #include <fstream>
3 #include <iostream>
4
5 #include <cstdlib>
6 #include <cstring>
7 #include <algorithm>
8 #include <cmath>
9
10 #include <queue>
11 #include <vector>
12 #include <map>
13 #include <set>
14 #include <stack>
15 #include <list>
16
17 typedef unsigned int uint;
18 typedef long long int ll;
19 typedef unsigned long long int ull;
20 typedef double db;
21 typedef long double ldb;
22
23 using namespace std;
24
25 inline int getint()
26 {
27 int res=0;
28 char c=getchar();
29 bool mi=false;
30 while(c<'0' || c>'9') mi=(c=='-'),c=getchar();
31 while('0'<=c && c<='9') res=res*10+c-'0',c=getchar();
32 return mi ? -res : res;
33 }
34 inline ll getll()
35 {
36 ll res=0;
37 char c=getchar();
38 bool mi=false;
39 while(c<'0' || c>'9') mi=(c=='-'),c=getchar();
40 while('0'<=c && c<='9') res=res*10+c-'0',c=getchar();
41 return mi ? -res : res;
42 }
43
44 //==============================================================================
45 //==============================================================================
46 //==============================================================================
47 //==============================================================================
48
49 db eps=1e-6;
50
51 struct point
52 {
53 db x,y;
54 point(db x=0,db y=0):x(x),y(y){}
55 point operator+(point f) { return point(x+f.x,y+f.y); }
56 point operator*(db f) { return point(x*f,y*f); }
57 point operator*(point f) { return x*f.y-y*f.x; }
58 point operator-(point f) { return point(x-f.x,y-f.y); }
59 point operator()(point f) { return point(f.x-x,f.y-y); }
60 point&operator=(point f) { memcpy(this,&f,sizeof(point)); return *this; }
61 };
62
63 db dist(const point &a,const point &b)
64 { return sqrt((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y)); }
65
66 point cc(point&a,point&b,point&c)
67 {
68 point ret;
69 db a1=b.x-a.x,b1=b.y-a.y,c1=(a1*a1+b1*b1)*0.5;
70 db a2=c.x-a.x,b2=c.y-a.y,c2=(a2*a2+b2*b2)*0.5;
71 db d=a1*b2-a2*b1;
72 if(abs(d)<1e-12) return (b+c)*0.5;
73 ret.x=a.x+(c1*b2-c2*b1)/d;
74 ret.y=a.y+(a1*c2-a2*c1)/d;
75 return ret;
76 }
77
78 int n;
79 point a[1005000];
80
81 void putres(db a,db b,db r)
82 {printf("%.2f %.2f %.2f\n",a,b,r);}
83
84 int main()
85 {
86 srand(23333);
87
88 n=getint();
89 for(int i=0;i<n;i++)
90 scanf("%lf%lf",&a[i].x,&a[i].y);
91
92 if(n==0) { putres(0,0,0); return 0; }
93 if(n==1) { putres(a[0].x,a[0].y,0); return 0; }
94 if(n==2)
95 {
96 putres( (a[0]+a[1]).x*0.5,
97 (a[0]+a[1]).y*0.5,
98 dist(a[0],a[1])*0.5);
99
100 return 0;
101 }
102
103 for(int i=0;i<n;i++)
104 {
105 int p=rand()%n;
106 swap(a[i],a[p]);
107 }
108 point O; db R=0.0;
109 for(int i=2;i<n;i++)
110 if(dist(a[i],O)>=R+eps)
111 {
112 O=a[i];
113 R=0.0;
114
115 for(int j=0;j<i;j++)
116 if(dist(a[j],O)>=R+eps)
117 {
118 O=(a[i]+a[j])*0.5;
119 R=dist(a[i],a[j])*0.5;
120
121 for(int k=0;k<j;k++)
122 if(dist(a[k],O)>=R+eps)
123 {
124 O=cc(a[i],a[j],a[k]);
125 R=dist(a[i],O);
126 }
127 }
128 }
129
130 putres(O.x,O.y,R);
131
132 return 0;
133 }
。。。