[ 随机增量法 ] BZOJ1336 && 1337 && 2823

来源:互联网 发布:hadoop 处理数据 编辑:程序博客网 时间:2024/06/06 00:07

先将所有点随机排列,然后枚举每个点,如果超出圆的范围就再枚举另外两个点求出圆心。
这样看上去是 O(n3) 的,实际上可以证明期望为 O(n)
求圆心可以假设出圆的方程然后解三元一次方程组。注意判断共线的情况。

#include<bits/stdc++.h>using namespace std;typedef double db;const int N=1000010;const db Eps=1e-10;typedef pair<db,db>abcd;#define X first#define Y secondint k,n,m,p;abcd a[N];db x,y,r;inline db Dis(int n){    return sqrt((a[n].X-x)*(a[n].X-x)+(a[n].Y-y)*(a[n].Y-y));}inline db Cross(db X1,db Y1,db X2,db Y2){    return X1*Y2-X2*Y1;}inline db Max(db a,db b,db c){    return max(a,max(b,c));}inline db Min(db a,db b,db c){    return min(a,min(b,c));}inline db Abs(db x){    return x>0?x:-x;}inline void Get(db X1,db Y1,db X2,db Y2,db X3,db Y3){    if(Abs(Cross(X2-X1,Y2-Y1,X3-X2,Y3-Y2))<Eps){        x=(Max(X1,X2,X3)+Min(X1,X2,X3))/2;        y=(Max(Y1,Y2,Y3)+Min(Y1,Y2,Y3))/2;        return;    }    db A=X1*X1+Y1*Y1,B=X2*X2+Y2*Y2,C=X3*X3+Y3*Y3;    db a1=X3-X2,a2=X1-X3,a3=X1-X2;    db b1=Y3-Y2,b2=Y1-Y3,b3=Y1-Y2;    x=(b1*A+b2*B-b3*C)/(b1*X1+b2*X2-b3*X3)/2;    y=(a1*A+a2*B-a3*C)/(a1*Y1+a2*Y2-a3*Y3)/2;}int main(){    scanf("%d",&n);    for(int i=1;i<=n;i++)scanf("%lf%lf",&a[i].X,&a[i].Y);    random_shuffle(a+1,a+n+1);    x=a[1].X;y=a[1].Y;    for(int i=2;i<=n;i++){        if(Dis(i)>r+Eps){            x=(a[1].X+a[i].X)/2;y=(a[1].Y+a[i].Y)/2;r=Dis(i);            for(int j=2;j<i;j++)            if(Dis(j)>r+Eps){                x=(a[i].X+a[j].X)/2;y=(a[i].Y+a[j].Y)/2;r=Dis(i);                for(int k=1;k<j;k++)                if(Dis(k)>r+Eps){                    Get(a[i].X,a[i].Y,a[j].X,a[j].Y,a[k].X,a[k].Y);                    r=Dis(i);                }            }        }    }    printf("%.2lf %.2lf %.2lf\n",x,y,r);    return 0;}
原创粉丝点击