题解 P2533 【[AHOI2012]信号塔】

消失的海岸线

2017-09-19 15:54:06

Solution

人话题意:给出平面上 N 个点,N<=10^6,请求出一个半径最小的圆覆盖住所有的点,并求出该点的坐标与半径。 即经典的最小圆覆盖问题,在此我们介绍随机增量法: 随机增量法是一个可以在 **期望**$O(n)$ 时间内求出最小圆覆盖的算法,首先它的算法流程是这样的 枚举第一个点 $i$,若不在目前圆内,设它为圆心 枚举第二个点 $j$,若不在当前圆内,设当前圆为以 $i,j$ 为直径的圆 枚举第三个点 $k$,若不在当前圆内,设当前圆为 $i,j,k$ 的外接圆 ###正确性 显然最优解一定是两个点为直径的圆或者一个三角形的外接圆,否则肯定能缩的更小。那么这么枚举的正确性是比较显然的了 ###时间复杂度 这是一个重点,这么做看似是$O(n^3)$ 的,不过对于**随机顺序**的点,是可以**期望**$ O(n)$ 的。下面考虑证明: 显然,最后一层循环枚举从 $1~j$,只要进入循环就一定要跑完,所以是$O(j)$ 的 考虑倒数第二层循环,什么情况下会进入第三层循环呢?仅当 $j$ 不在前 $j-1$ 个点形成的圆中,考虑 $j$ 个点形成的圆是由三个点确定的,那么第 $j$ 个 (最后一个点) 若是三个点之一,则需要扩大圆,否则不需要进入第三层循环,这个概率是$\frac{3}{j}$ 的,所以第二层的复杂度是$O(i)$ 的 同理,第一层的复杂度就是$O(n)$ 的了 ###实现 以此题为例,给出在下的AC代码: ```cpp #include <cmath> #include <queue> #include <cstdio> #include <iomanip> #include <cstdlib> #include <cstring> #include <iostream> #include <algorithm> #define N 500010 #define eps 1e-6 #define ll long long using namespace std; inline int read() { int x=0,f=1;char ch=getchar(); while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();} while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();} return x*f; } struct point { double x,y; }a[N],O; double R; int n; double dis(point x,point y) {return sqrt((x.x-y.x)*(x.x-y.x)+(x.y-y.y)*(x.y-y.y));} bool in_cir(point x) {return dis(x,O)-R<eps;} point get_O(point x1,point x2,point x3) { double a,b,c,d,e,f; point ans; a=x2.x-x1.x,b=x2.y-x1.y,c=x3.x-x2.x,d=x3.y-x2.y; e=x2.x*x2.x+x2.y*x2.y-x1.x*x1.x-x1.y*x1.y; f=x3.x*x3.x+x3.y*x3.y-x2.x*x2.x-x2.y*x2.y; ans.x=(f*b-e*d)/(c*b-a*d)/2; ans.y=(a*f-e*c)/(a*d-b*c)/2; return ans; } int main() { n=read(); for(int i=1;i<=n;i++) scanf("%lf %lf",&a[i].x,&a[i].y); for(int i=1;i<=n;i++) swap(a[i],a[rand()%n+1]); O=a[1]; for(int i=1;i<=n;i++) if(!in_cir(a[i])) { O=a[i]; for(int j=1;j<i;j++) if(!in_cir(a[j])) { O.x=(a[i].x+a[j].x)/2; O.y=(a[i].y+a[j].y)/2; R=dis(a[i],a[j])/2; for(int k=1;k<j;k++) if(!in_cir(a[k])) { O=get_O(a[i],a[j],a[k]); R=dis(O,a[i]); } } } printf("%.2lf %.2lf %.2lf",O.x,O.y,R); } ``` 为了避免可能存在的markdown格式错误,可以在本人的博客中看到同样的内容 http://www.zgz233.xyz/2017/07/10/bzoj-133613372823-balkan2002alien%E6%9C%80%E5%B0%8F%E5%9C%86%E8%A6%86%E7%9B%96ahoi2012%E4%BF%A1%E5%8F%B7%E5%A1%94/