题目大意:RT
题解:随机增量法……
设圆
Ci
表示前i个点的最小覆盖圆,当加入点i时,若其在
Ci−1
外则说明
Ci
肯定经过第i个点,以点0和点i确定
Ci
然后再从前i个点中找到类似的j,前j个点中找到类似的k,三点定圆
求三角形外心可以直接按照定义……
最小圆必定是可以通过不断放大半径,直到所有以任意点为圆心,半径为半径的圆存在交点,此时的半径就是最小圆。所以上述定理可以通过这个思想得到。这个做法复杂度是O(n)的,当加入圆的顺序随机时,因为三点定一圆,所以不在圆内概率是3/i,求出期望可得是O(n)
我的收获:模板++
#include <bits/stdc++.h>
using namespace std;
#define eps 1e-8
const int N=100005;
int n;
double R;
struct Point{
double x,y;
Point(){}
Point(double _,double __){x=_,y=__;}
void read(){scanf("%lf%lf",&x,&y);}
}p[N],C;
typedef Point Vector;
Vector operator + (Vector A,Vector B){return Vector(A.x+B.x,A.y+B.y);}
Vector operator - (Vector A,Vector B){return Vector(A.x-B.x,A.y-B.y);}
Vector operator * (Vector A,double p){return Vector(A.x*p,A.y*p);}
Vector operator / (Vector A,double p){return Vector(A.x/p,A.y/p);}
double Dot(Vector A,Vector B){return A.x*B.x+A.y*B.y;}
double Cross(Vector A,Vector B){return A.x*B.y-A.y*B.x;}
Point Mid(Point A,Point B){return Point((A.x+B.x)/2,(A.y+B.y)/2);}
Vector Normal(Vector A){return Vector(-A.y,A.x);}
double Dis(Point A,Point B){return sqrt(Dot(A-B,A-B));}
struct Line{
Point P;
Vector V;
Line(){}
Line(Point _,Vector __){P=_,V=__;}
};
Point GetLineIntersection(Line A,Line B){
double t=Cross(B.V,A.P-B.P)/Cross(A.V,B.V);
return A.P+A.V*t;
}
Point Circumcenter(Point A,Point B,Point C){
Vector V1=Normal(B-A),V2=Normal(C-A);
Line L1=Line(Mid(A,B),V1),L2=Line(Mid(A,C),V2);
return GetLineIntersection(L1,L2);
}
void Min_cover_circle()
{
random_shuffle(p,p+n);
C=p[0];R=0;
for(int i=1;i<n;i++) if(Dis(p[i],C)>R)
{
C=(p[i]+p[0])/2;R=Dis(p[i],C);
for(int j=0;j<i;j++) if(Dis(p[j],C)>R)
{
C=(p[i]+p[j])/2;R=Dis(p[i],C);
for(int k=0;k<j;k++) if(Dis(p[k],C)>R)
{
C=Circumcenter(p[i],p[j],p[k]);
R=Dis(p[i],C);
}
}
}
}
void work()
{
Min_cover_circle();
printf("%.10lf\n%.10lf %.10lf\n",R,C.x,C.y);
}
void init()
{
scanf("%d",&n);
for(int i=0;i<n;i++) p[i].read();
}
int main()
{
init();
work();
return 0;
}