给出N个点,让你画一个最小的包含所有点的圆。
标签:
给出N个点,让你画一个最小的包含所有点的圆。
先给出点的个数N,2<=N<=100000,再给出坐标Xi,Yi.(-10000.0<=xi,yi<=10000.0)
输出圆的半径,及圆心的坐标
最小圆覆盖裸题,随机增量法
这道题有个需要注意的地方,输出的时候不要只输出2位小数,可能会WA,可以考虑直接输出
直接把课件黏上来= =
#include<cstdio> #include<iostream> #include<algorithm> #include<cstring> #include<cmath> #include<vector> #include<queue> #include<map> #include<set> #include<stack> #include<cstdlib> #include<string> #include<bitset> #include<iomanip> #define INF 1000000000 #define fi first #define se second #define N 100005 #define MP(x,y) make_pair(x,y) using namespace std; typedef long long LL; typedef pair<int,int> pii; typedef long double Double; struct Vector { double x,y; Vector(double X=0,double Y=0) {x=X,y=Y;} }; typedef Vector Point; typedef vector<Point> Polygon; const double eps=1e-12; const double pi=acos(-1.0); struct Line { Point P; Vector v; double ang; Line() {} Line(Point P,Vector v):P(P),v(v) {ang=atan2(v.y,v.x);} bool operator<(const Line &L) const {return ang<L.ang;} }; int dcmp(double x) {if(fabs(x)<eps) return 0; else return x<0? -1:1;} 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});} bool operator < (const Vector& a,const Vector& b) {return a.x<b.x||(a.x==b.x&&a.y<b.y);} bool operator == (const Vector& a,const Vector& b) {return dcmp(a.x-b.x)==0&&dcmp(a.y-b.y)==0;} double Dot(Vector A,Vector B) {return A.x*B.x+A.y*B.y;} double Len(Vector A) {return sqrt(Dot(A,A));} double Cross(Vector A,Vector B) {return A.x*B.y-A.y*B.x;} Vector Rotate(Vector A,double rad) {return ((Vector){A.x*cos(rad)-A.y*sin(rad), A.x*sin(rad)+A.y*cos(rad)});} Point GLI(Point P,Vector v,Point Q,Vector w) {Vector u=P-Q; double t=Cross(w,u)/Cross(v,w); return P+v*t;} Point GLI(Line a,Line b) {Vector u=a.P-b.P; double t=Cross(b.v,u)/Cross(a.v,b.v);return a.P+a.v*t;} Point Center_of_gravity(Point A,Point B,Point C) { Point P=(A+B)/2,Q=(A+C)/2; Vector v=Rotate(B-A,pi/2),w=Rotate(C-A,pi/2); if(dcmp(Len(Cross(v,w)))==0)//这是三点一线的情况 { if(dcmp(Len(A-B)+Len(B-C)-Len(A-C))==0) return (A+C)/2; if(dcmp(Len(A-C)+Len(B-C)-Len(A-B))==0) return (A+B)/2; if(dcmp(Len(A-B)+Len(A-C)-Len(B-C))==0) return (B+C)/2; } return GLI(P,v,Q,w); } double Min_Cover_Circle(Point *p,int n,Point &c) { random_shuffle(p,p+n); c=p[0]; double r=0; int i,j,k; for(i=1;i<n;i++) if(dcmp(Len(c-p[i])-r)>0) { c=p[i],r=0; for(j=0;j<i;j++) if(dcmp(Len(c-p[j])-r)>0) { c=(p[i]+p[j])/2; r=Len(c-p[i]); for(k=0;k<j;k++) if(dcmp(Len(c-p[k])-r)>0) { c=Center_of_gravity(p[i],p[j],p[k]); r=Len(c-p[i]); } } } return r; } #define MAXN 100010 Point Po[MAXN]; int main() { srand(20000104); int n; scanf("%d",&n); for (int i=1; i<=n; i++) { double x,y; scanf("%lf%lf",&x,&y); Po[i-1]=Point(x,y); } Point c; printf("%lf\n",Min_Cover_Circle(Po,n,c)); printf("%lf %lf",c.x,c.y); return 0; }
【BZOJ-1336&1337】Alie最小圆覆盖 最小圆覆盖(随机增量法)
标签:
原文地址:http://www.cnblogs.com/DaD3zZ-Beyonder/p/5674663.html