BZOJ 2823: [AHOI2012]信号塔
题目:http://www.lydsy.com/JudgeOnline/problem.php?id=2823
随机增量法。不断加点维护圆,主要是三点共圆那里打得烦(其实也就是个两中垂线求交点+联立方程求交点而已TAT。。
#include<cstring> #include<iostream> #include<cstdio> #include<algorithm> #include<cmath> #define rep(i,l,r) for (int i=l;i<=r;i++) #define down(i,l,r) for (int i=l;i>=r;i--) #define clr(x,y) memset(x,y,sizeof(x)) #define maxn 1000009 #define eps 1e-6 using namespace std; typedef unsigned long long ll; struct P{double x,y; }a[maxn],o; double r; int n; int read(){ int x=0,f=1; char ch=getchar(); while (!isdigit(ch)){ if (ch=='-') f=-1; ch=getchar(); } while (isdigit(ch)){ x=x*10+ch-'0'; ch=getchar(); } return x*f; } P get2(P a,P b){ P tmp; tmp.x=(a.x+b.x)/2; tmp.y=(a.y+b.y)/2; return tmp; } double sqr(double x){ return x*x; } double dis(P a,P b){ return sqrt(sqr(a.x-b.x)+sqr(a.y-b.y)); } P cross(double a1,double a2,double b1,double b2,double c1,double c2){ P tmp; tmp.x=(c2*b1-c1*b2)/(a1*b2-a2*b1); tmp.y=(c2*a1-c1*a2)/(b1*a2-b2*a1); return tmp; } P get3(P a,P b,P c){ P tmp; double a1=b.x-a.x,b1=b.y-a.y,c1=(sqr(a.y)-sqr(b.y)+sqr(a.x)-sqr(b.x))/2; double a2=c.x-a.x,b2=c.y-a.y,c2=(sqr(a.x)+sqr(a.y)-sqr(c.x)-sqr(c.y))/2; return tmp=cross(a1,a2,b1,b2,c1,c2); } int cmp(double x){ if (fabs(x)<eps) return 0; if (x>0) return 1; return -1; } int main(){ n=read(); rep(i,1,n){ scanf("%lf%lf",&a[i].x,&a[i].y); } int x,y; rep(i,1,n) { x=rand()%n+1; y=rand()%n+1; swap(a[x],a[y]); } o=a[1]; r=0; rep(i,2,n){ if (cmp(dis(a[i],o)-r)<0) continue; o=a[i]; r=0; rep(j,1,i-1){ if (cmp(dis(a[j],o)-r)<0) continue; o=get2(a[i],a[j]); r=dis(a[j],o); rep(k,1,j-1) { if (cmp(dis(a[k],o)-r)<0) continue; o=get3(a[i],a[j],a[k]); r=dis(a[k],o); } } } printf("%.2lf %.2lf ",o.x,o.y); printf("%.2lf\n",r); return 0; }