ZOJ1450 Minimal Circle

不断添加圆,维护最小圆。如果添加的点i在圆内,不动,否则:

  问题转化为求1~I的最小圆:求出1与I的最小圆,并且扫描j=2~(I-1),维护(1)+(i)+(2~j)的最小圆,如果找到J不在最小圆内,问题转化为:求(1~J)+(i)的最小圆。求出I与J的最小圆,继续扫描K=1~(j-1),找到不在最小圆内的,求出I J K三者最小圆,此时找到了(1~j)+(i)的最小圆,可以回到上一步(三点定一圆,所以1~(J-1)一定都在求出的最小圆上)。

  这个做法复杂度是O(n)的,当加入圆的顺序随机时,因为三点定一圆,所以不在圆内概率是3/i,求出期望可得是On.

以上是百度文库的内容,自己做了些删改

以下代码的时间是10ms,内存180kb

#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include<math.h>
struct point
{
    double x;
    double y;
};
struct T
{
    point heart;
    double d;
}circle;
point a[102];
double dis(point a,point b)
{
    return sqrt((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y));
}
bool check(point p,point q,point k)//确定三点是否在同一直线上
{
    if((p.x-k.x)*(q.y-k.y)-(q.x-k.x)*(p.y-k.y)==0)
    {
        return true;
    }
    return false;
}
void fin2(point p,point q,int n)
{
    int i;
    circle.heart.x=(p.x+q.x)/2;
    circle.heart.y=(p.y+q.y)/2;
    circle.d=dis(p,q)/2;
    for(i=1;i<=n;i++)
    {
        if(dis(a[i],circle.heart)<=circle.d)
        {
            continue;
        }
        if(check(p,q,a[i]))//三点一线
        {
            double d[3];
            d[0]=dis(q,p);
            d[1]=dis(q,a[i]);
            d[2]=dis(p,a[i]);
            if(d[0]>=d[1]&&d[0]>=d[2])
            {
                circle.heart.x=(p.x+q.x)/2;
                circle.heart.y=(p.y+q.y)/2;
                circle.d=d[0]/2;
            }
            else if(d[1]>=d[0]&&d[1]>=d[2])
            {
                circle.d=d[1]/2;
                circle.heart.x=(q.x+a[i].x)/2;
                circle.heart.y=(q.y+a[i].y)/2;
            }
            else
            {
                circle.d=d[2]/2;
                circle.heart.x=(p.x+a[i].x)/2;
                circle.heart.y=(p.y+a[i].y)/2;
            }
        }
        else
        {
            double c1=(p.x*p.x+p.y*p.y-q.x*q.x-q.y*q.y)/2.0;
            double c2=(p.x*p.x+p.y*p.y-a[i].x*a[i].x-a[i].y*a[i].y)/2.0;
            
            circle.heart.x=(c1*(p.y-a[i].y)-c2*(p.y-q.y))/((p.x-q.x)*(p.y-a[i].y)-(p.x-a[i].x)*(p.y-q.y));
            circle.heart.y=(c1*(p.x-a[i].x)-c2*(p.x-q.x))/((p.y-q.y)*(p.x-a[i].x)-(p.y-a[i].y)*(p.x-q.x));
            circle.d=dis(circle.heart,p);
        }
    }
}
void fin(point p,int n)
{
    circle.heart.x=(a[1].x+p.x)/2;
    circle.heart.y=(a[1].y+p.y)/2;
    circle.d=dis(p,a[1])/2;
    int i;
    for(i=2;i<=n;i++)
    {
        if(dis(a[i],circle.heart)>circle.d)
        {
            fin2(p,a[i],i-1);
        }
    }
}
int main()
{
    int n;
    while(scanf("%d",&n),n)
    {
        int i,j;
        for(i=1;i<=n;i++)
        {
            scanf("%lf %lf",&a[i].x,&a[i].y);
        }
        if(n==1)
        {
            printf("%.2f %.2f 0.00\n",a[0].x,a[0].y);
            continue;
        }
        circle.heart.x=(a[1].x+a[2].x)/2;
        circle.heart.y=(a[1].y+a[2].y)/2;
        circle.d=dis(a[2],a[1])/2;
        for(i=3;i<=n;i++)
        {
            if(dis(circle.heart,a[i])>circle.d)
            {
                fin(a[i],i-1);
            }
        }
        printf("%.2f %.2f %.2f\n",circle.heart.x,circle.heart.y,circle.d);
    }
    return 0;
}

 

 

posted @ 2012-07-15 11:18  willzhang  阅读(228)  评论(0编辑  收藏  举报