bzoj2823[AHOI2012]信号塔

随机增量法求最小覆盖圆,主要就是圆心坐标神烦,后来看到了ACdreamer的一个简洁版本,虽然还没明白是为什么但是比窝那个短多了

#include<iostream>
#include<cstdio>
#include<cmath>
#include<cstring>
#include<cstdlib>
#include<algorithm>
#include<iomanip>
#define LL long long
#define fo(i,a,b) for(int i=a;i<=b;i++)
using namespace std;
#define N 1000005
#define eps 1e-8
struct P
{
	double x,y;
}d[N];
int n;

double dis(P a,P b)
{
	return sqrt((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y));
}

P get(P A,P B,P C)
{
	P t;  
    double a1=B.x-A.x,b1=B.y-A.y,c1=(a1*a1+b1*b1)/2;  
    double a2=C.x-A.x,b2=C.y-A.y,c2=(a2*a2+b2*b2)/2;  
    double d=a1*b2-a2*b1;  
    t.x=A.x+(c1*b2-c2*b1)/d;  
    t.y=A.y+(a1*c2-a2*c1)/d;  
    return t;
}  

P get(P a,P b)
{
	return (P){(a.x+b.x)/2,(a.y+b.y)/2};
}

int main()
{
	scanf("%d",&n);
	fo(i,1,n) scanf("%lf%lf",&d[i].x,&d[i].y);
	P t=d[1];double r=0.0;
	fo(i,1,n)
	{
		if (dis(d[i],t)<=r+eps) continue;
		t=d[i];r=0;
		fo(j,1,i-1)
		{
			if (dis(d[j],t)<=r+eps) continue;
			t=get(d[i],d[j]);r=dis(d[j],t);
			fo(k,1,j-1)
			{
				if (dis(d[k],t)<=r+eps) continue;
				t=get(d[i],d[j],d[k]);r=dis(d[k],t);
			}
		}
	}
	printf("%.2lf %.2lf %.2lf\n",t.x,t.y,r);
	return 0;
}


你可能感兴趣的:(计算几何)