uva 1473 - Dome of Circus

題意:給定 n 個空間中的點,任務是找一個底面在 z=0 平面上,中心在(0,0,0)的體積最小的圓錐,包含所有點。

\epsfbox{p4986.eps}

#include<iostream>
#include<cmath>
#include<algorithm>
#include<iomanip>
#define pi (2.0*asin(1.0))
#define div(a) ((a)*(a)*(a))
#define eps 1e-6

using namespace std;
const double inf=8000000000000000000;

int m,n;

int sig(double a)
{
    return (a>eps)-(a<-eps);
}

struct point
{
    double x,y;
    point(double xx=0,double yy=0):x(xx),y(yy){}
}p[10010],ch[10010];

bool operator < (point a,point b)
{
    return sig(a.x-b.x)<0 || (sig(a.x-b.x)==0 && sig(a.y-b.y)<0);
}
point operator - (point a,point b)
{
    return point(a.x-b.x,a.y-b.y);
}
double cross(point a,point b)
{
    return a.x*b.y-a.y*b.x;
}
void convex()
{
	int i;
    sort(p,p+n);
    m=0;
    for(i=0;i<n;i++)
    {
        while(m>1 && sig(cross(ch[m-1]-ch[m-2],p[i]-ch[m-2]))<=0) m--;
        ch[m++]=p[i];
    }
    int k=m;
    for(i=n-2;i>=0;i--)
    {
        while(m>k && sig(cross(ch[m-1]-ch[m-2],p[i]-ch[m-2]))<=0) m--;
        ch[m++]=p[i];
    }
    if(n>1) m--;
}

int main()
{
    int i,mx;
    double x,y,z,k,k1,k2,mv,mk,v;
    while(cin>>n)
    {
        for(i=0;i<n;i++)
        {
            cin>>x>>y>>z;
            p[i]=point(sqrt(x*x+y*y),z);
        }
        convex();
        mv=inf;
        int i1,i2;
        if(m>1)
        {
            k2=inf;
            for(i=0;i<m;i++)
            {
                i2=(i+1)%m;
                if(sig(ch[i2].x-ch[i].x)<0)
                {
                    k=2*ch[i].y/ch[i].x;
                    k1=k2;
                    k2=(ch[i2].y-ch[i].y)/(ch[i].x-ch[i2].x);
                    if(sig(k2)<=0) break;
                    if(sig(k-k2)<0) k=k2;
                    else if(sig(k-k1)>0) k=k1;
                    v=k/3*pi*div(ch[i].x+ch[i].y/k);
                    if(sig(mv-v)>0)
                    {
                        mv=v;
                        mx=i;mk=k;
                    }
                }
                else if(sig(ch[i2].x-ch[i].x)==0 && ch[i2].y<ch[i].y) break;
            }
            i%=m;i1=(m+i-1)%m;
            if(sig(ch[i1].x-ch[i].x)==0) k1=-1;
            else k1=(ch[i].y-ch[i1].y)/(ch[i1].x-ch[i].x);
            k=2*ch[i].y/ch[i].x;
            if(sig(k1)>0 && sig(k-k1)>0) k=k1;
            v=k/3*pi*div(ch[i].x+ch[i].y/k);
            if(sig(mv-v)>0)
            {
                mv=v;
                mx=i;mk=k;
            }
            x=ch[mx].x;y=ch[mx].y;
            k=mk;
        }
        else
        {
            x=ch[0].x;y=ch[0].y;
            k=2*y/x;
        }
        double h=y+k*x;
        double x=h/k;
        cout<<fixed<<setprecision(3)<<h<<" "<<x<<endl;
    }
    return 0;
}


發佈了116 篇原創文章 · 獲贊 217 · 訪問量 11萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章