zoj1450

题目大意:

找一个圆覆盖一些点,同时面积最小

解题思路:

点集的最小圆覆盖

代码如下:

#include<stdio.h>
#include<math.h>
const int maxn=1005;
const double eps=1e-6;

struct TPoint{
  double x,y;
  TPoint operator-(TPoint &a){
    TPoint p1;
    p1.x=x-a.x;
    p1.y=y-a.y;
    return p1;
  }
};

struct TCircle{
  double r;
  TPoint centre;
};

struct TTriangle{
  TPoint t[3];       
};

TCircle c;
TPoint a[maxn];

double distance(TPoint p1,TPoint p2)
{
  TPoint p3;
  p3.x=p2.x-p1.x;
  p3.y=p2.y-p1.y;
  return sqrt(p3.x*p3.x+p3.y*p3.y);
}

double triangleArea(TTriangle t)
{
  TPoint p1,p2;
  p1=t.t[1]-t.t[0];
  p2=t.t[2]-t.t[0];
  return fabs(p1.x*p2.y-p1.y*p2.x)/2;;
}

TCircle circumcircleOfTriangle(TTriangle t)
{
  TCircle tmp;
  double a,b,c,c1,c2;
  double xA,yA,xB,yB,xC,yC;
  a=distance(t.t[0],t.t[1]);
  b=distance(t.t[1],t.t[2]);
  c=distance(t.t[2],t.t[0]);

  tmp.r=a*b*c/triangleArea(t)/4;

  xA=t.t[0].x;
  yA=t.t[0].y;
  xB=t.t[1].x;
  yB=t.t[1].y;
  xC=t.t[2].x;
  yC=t.t[2].y;
  c1=(xA*xA+yA*yA-xB*xB-yB*yB)/2;
  c2=(xA*xA+yA*yA-xC*xC-yC*yC)/2;
  tmp.centre.x=(c1*(yA-yC)-c2*(yA-yB))/
           ((xA-xB)*(yA-yC)-(xA-xC)*(yA-yB));
  tmp.centre.y=(c1*(xA-xC)-c2*(xA-xB))/
           ((yA-yB)*(xA-xC)-(yA-yC)*(xA-xB));
  return tmp;
}

TCircle MinCircle2(int tce,TTriangle ce)
{
  TCircle tmp;
  if(tce==0)  tmp.r=-2;
  else if(tce==1)
  {
    tmp.centre=ce.t[0];
    tmp.r=0;
  }
  else if(tce==2)
  {
    tmp.r=distance(ce.t[0],ce.t[1])/2;
    tmp.centre.x=(ce.t[0].x+ce.t[1].x)/2;
    tmp.centre.y=(ce.t[0].y+ce.t[1].y)/2;
  }
  else if(tce==3)
    tmp=circumcircleOfTriangle(ce);
  return tmp;
}

void MinCircle(int t,int tce,TTriangle ce)
{
  int i,j;
  TPoint tmp;
  c=MinCircle2(tce,ce);
  if(tce==3)  return;
  for(i=1;i<=t;i++)
  {
    if(distance(a[i],c.centre)>c.r)
    {
      ce.t[tce]=a[i];
      MinCircle(i-1,tce+1,ce);
      tmp=a[i];
      for(j=i;j>=2;j--)
      {
        a[j]=a[j-1];
      }
      a[1]=tmp;
    }
  }
}

int main()
{
  int n,i;
  while(scanf("%d",&n)!=EOF&&n)
  {
    for(i=1;i<=n;i++)
    {
      scanf("%lf%lf",&a[i].x,&a[i].y);
    }
    TTriangle ce;
    MinCircle(n,0,ce);
    printf("%.2lf %.2lf %.2lf\n", c.centre.x, c.centre.y, c.r);
  }
  return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值