最小圆覆盖
#include <cstdio> #include <cmath> #include <iostream> #define eps 1e-5 #define LDB long double using namespace std; struct point{ LDB x,y; }p[500001],o; int n; LDB d; LDB dis(point a,point b){ return(sqrt((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y))); } point midpoint(point a,point b){ point ret; ret.x=(a.x+b.x)/2;ret.y=(a.y+b.y)/2; return ret; } point geto(point a,point b,point c){ point mid1=midpoint(a,b),mid2=midpoint(a,c); point ret; LDB ta1=atan2(a.x-b.x,b.y-a.y),ta2=atan2(a.x-c.x,c.y-a.y),b1,b2; if (fabs(ta1-acos(-1)*0.5)<eps){ b2=mid2.y-tan(ta2)*mid2.x; ret.x=mid1.x;ret.y=tan(ta2)*mid1.x+b2; return ret; } if (fabs(ta2-acos(-1)*0.5)<eps){ b1=mid1.y-tan(ta1)*mid1.x; ret.x=mid2.x;ret.y=tan(ta1)*mid2.x+b1; return ret; } b1=mid1.y-tan(ta1)*mid1.x; b2=mid2.y-tan(ta2)*mid2.x; ret.x=(b2-b1)/(tan(ta1)-tan(ta2)),ret.y=b1+tan(ta1)*ret.x; return ret; }//求三点确定的圆 int main(){ scanf("%d",&n); point o; o=p[1]; LDB r=0; for (register int i=2;i<=n;i++){ if (dis(o,p[i])<r+eps) continue; o=midpoint(p[1],p[i]),r=dis(o,p[i]); for (register int j=2;j<i;j++){ if (dis(o,p[j])<r+eps) continue; o=midpoint(p[i],p[j]),r=dis(o,p[j]); for (register int k=1;k<j;k++){ if (dis(o,p[k])<r+eps) continue; o=geto(p[i],p[j],p[k]); r=dis(p[i],o); } } } //r为圆半径,o为圆心 }
复杂度o(n)