HDU 3756 && UVALive 4986 Dome of Circus Dome of Circus(计算几何基础+三分)

 

Sample Input
3
1
1.00 0.00 1.00
2
1.00 0.00 1.00
0.00 1.50 0.50
3
1.00 0.00 1.00
0.00 1.50 0.50
-0.50 -0.50 1.00
Sample Output
3.000 1.500
2.000 2.000
2.000 2.000

在三维坐标上有 n 个点,所有的 z 坐标都大于等于 0,求一个最小的圆锥使得包含所有的点 

可以很容易想到圆锥高度的最小值是所有 z 坐标的最大值,然后确定圆锥的高度 h 即可,因为有了高度,很容易求出圆锥的底面半径

  • 如下图所示,点的坐标已经给出,所以 r ,z 已知,根据三角形相似,得:
  • \frac{x}{x+r}=\frac{z}{h},所以求得
  • 底面半径 R=\frac{zr}{h-z}+r
  • 这样根据 y=\frac{\pi R^2h}{3} 得到一个关于 h 的函数
  • 可以求得 y 的二阶导 >=0 ,所以 y 是一个凹函数,三分枚举即可

 

const int N=1e4+5;

    int i,j,k;
    int n,m,t;
    struct Point
    {
        double x,y,z;
        Point(double x=0,double y=0,double z=0):x(x),y(y),z(z){}
    };

typedef Point Vector;
Point a[N];
double r[N];

double getR(double h)
{
    double ans=0;
    for(int i=1;i<=n;i++) ans=max(ans,a[i].z*r[i]/(h-a[i].z)+r[i]);
    return ans;
}

int main()
{
    //IOS;
    rush(){
        sd(n);
        double L=0,R=1111,midl,midr;
        for(int i=1;i<=n;i++){
            sfff(a[i].x,a[i].y,a[i].z);
            r[i]=sqrt(a[i].x*a[i].x+a[i].y*a[i].y);
            L=max(a[i].z,L);
        }
        while(fabs(R-L)>eps){
            midl=(L+R)/2;
            midr=(midl+R)/2;
            double r1=getR(midl),r2=getR(midr);
            if(r1*r1*midl<r2*r2*midr) R=midr;
            else L=midl;
        }
        printf("%.3lf %.3lf\n",L,getR(L));
    }
    //PAUSE;
    return 0;
}

 

已标记关键词 清除标记
©️2020 CSDN 皮肤主题: 酷酷鲨 设计师:CSDN官方博客 返回首页