bzoj 2823 信号塔|计算几何|随机增量法

经典的最小圆覆盖问题,推公式略恶心。

#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<algorithm>
#include<cmath>

 

#define md
#define ll long long
#define inf (int) 1e9
#define eps 1e-6
#define N 500010
using namespace std;
struct point { double x,y;} p[N];
int fcmp(double a,double b)
{
 if (a-b>eps) return 1;
 if (a-b<-eps) return -1;
 return 0;
}
point operator + (point a,point b) { return (point) {a.x+b.x,a.y+b.y};}
point operator - (point a,point b) { return (point){a.x-b.x,a.y-b.y}; }
point operator / (point a,double b) { return (point){a.x/b,a.y/b};}
double operator * (point a,point b) { return a.x*b.y-a.y*b.x;}
double dot(point a,point b) { return a.x*b.x+a.y*b.y;}
double len (point a) { return sqrt(a.x*a.x+a.y*a.y);}

 

point cal(point p1,point p2,point p3)
{
 point p;
 if (fcmp((p2-p1)*(p3-p1),0)==0)
 {
  if (dot(p2-p1,p3-p1)<0) p=(p2+p3)/2;
  else if (dot(p1-p2,p3-p2)<0) p=(p1+p3)/2;
  else p=(p1+p2)/2;
  return p;
 }
 double a1,a2,b1,b2,c1,c2;
 a1=-2*p1.x+2*p2.x; b1=p1.x*p1.x-p2.x*p2.x+p1.y*p1.y-p2.y*p2.y; c1=2*p1.y-2*p2.y;
 a2=-2*p2.x+2*p3.x; b2=p2.x*p2.x-p3.x*p3.x+p2.y*p2.y-p3.y*p3.y; c2=2*p2.y-2*p3.y;
 //printf("%.2lf %.2lf %.2lf       %.2lf %.2lf %.2lf\n",a1,b1,c1,a2,b2,c2);
 p.x=(c1*b2-b1*c2)/(a1*c2-a2*c1);
 p.y=(a1*p.x+b1)/c1;
 //printf("now: %.2lf %.2lf %.2lf\n",len(p1-p),len(p2-p),len(p3-p));
 return p;
}

 

int main()
{
 int n;
 scanf("%d",&n);
 for (int i=1;i<=n;i++) scanf("%lf%lf",&p[i].x,&p[i].y);
 for (int i=1;i<=n;i++) swap(p[i],p[rand()%n+1]);
 if (n==1) { printf("%.2lf %.2lf 0.00",p[1].x,p[1].y); return 0;}
 if (n==2) { point ans=(p[1]+p[2])/2; printf("%.2lf %.2lf %.2lf\n",ans.x,ans.y,len(ans-p[1])); return 0;}
 point o=p[1];  double r=0; //printf("ans: %.2lf %.2lf %.2lf\n",o.x,o.y,r);
 for (int i=2;i<=n;i++)
 {
  if (fcmp(len(p[i]-o),r)<=0) continue;
  o=(p[1]+p[i])/2; r=len(p[1]-o);
  for (int j=2;j<i;j++)
  {
   if (fcmp(len(p[j]-o),r)<=0) continue;
   o=(p[i]+p[j])/2; r=len(p[i]-o); //printf("%d %d %d\n",1,i,j);
   for (int k=1;k<j;k++)
   {
    if (fcmp(len(p[k]-o),r)<=0) continue;
    o=cal(p[i],p[j],p[k]); r=len(p[i]-o);
    //printf("%d %d %d\n",i,j,k);
   }
  }
 }
 printf("%.2lf %.2lf %.2lf\n",o.x,o.y,r);
 return 0;
}

 


你可能感兴趣的:(bzoj 2823 信号塔|计算几何|随机增量法)