hdu3932 Groundhog Build Home 计算几何+最小圆覆盖

思路:

本来想写的是求出凸包然后在凸包上\(O(n^3)\)进行暴力的算法.虽然平面上的随机点形成的凸包点数很少,不过显然如果直接给出一个凸包就直接卡掉了.

于是我学习的是随机增量法求最小圆覆盖.

网上题解很多,就不解释了(还不太懂),如果随机打乱一下的话,好像是能够做到期望\(O(n)\),相当厉害的算法.

一个麻烦就是求出三角形的外心,用了一大堆叉积来算好像很傻逼...

#include<cstdio>
#include<cstring>
#include<cctype>
#include<cmath>
#include<iostream>
#include<algorithm>
using namespace std;

#define N 1010

#define eps 1e-8
typedef double f2;
struct Point{
    f2 x,y;
    Point(){}
    Point(f2 _x,f2 _y):x(_x),y(_y){}
    bool operator<(const Point&B)const{return x<B.x;}
    Point operator+(const Point&B)const{return Point(x+B.x,y+B.y);}
    Point operator-(const Point&B)const{return Point(B.x-x,B.y-y);}
    Point operator*(const f2&p){return Point(p*x,p*y);}
    Point operator/(const f2&p){return Point(x/p,y/p);}
}P[N];
inline f2 sqr(const f2&x){return x*x;}
f2 Cross(const Point&a,const Point&b){return a.x*b.y-a.y*b.x;} 
f2 getdist(const Point&a,const Point&b){return sqrt(sqr(a.x-b.x)+sqr(a.y-b.y));}

struct Line{
    Point p,v;
    Line(){}
    Line(Point _p,Point _v):p(_p),v(_v){}
};
Point GetLineIntersection(Line L1,Line L2){
    return L1.p+L1.v*(Cross(L1.p-L2.p,L2.v)/Cross(L1.v,L2.v));
}
Point Getvert(const Point&a){return Point(-a.y,a.x);}
Point Getmid(const Point&a,const Point&b){return Point((a.x+b.x)/2,(a.y+b.y)/2);}

Line GetLine(const Point&a,const Point&b){
    return Line(Getmid(a,b),Getvert(a-b));
}
Point Getcenter(Point a,Point b,Point c){
    Point P[3]={a,b,c};sort(P,P+3);a=P[0],b=P[1],c=P[2];
    if(fabs(Cross(a-b,b-c))<eps)return Getmid(a,c);
    else return GetLineIntersection(GetLine(a,b),GetLine(b,c));
}
    
int main(){
    int X,Y,n;register int i,j,k;
    while(scanf("%d%d%d",&X,&Y,&n)!=EOF){
        for(i=1;i<=n;++i)scanf("%lf%lf",&P[i].x,&P[i].y);
        random_shuffle(P+1,P+n+1);
        Point center=P[1];f2 r=0;
        for(i=2;i<=n;++i){
            if(getdist(center,P[i])>r){
                center=P[i],r=0;
                for(j=1;j<i;++j){
                    if(getdist(center,P[j])>r){
                        center=Getmid(P[i],P[j]),r=getdist(P[i],P[j])*.5;
                        for(k=1;k<j;++k)
                            if(getdist(center,P[k])>r)center=Getcenter(P[i],P[j],P[k]),r=getdist(center,P[i]);
                    }
                }
            }
        }
        printf("(%.1lf,%.1lf).\n%.1lf\n",center.x,center.y,r);
    }
    return 0;
}