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 已知,根据三角形相似,得:
,所以求得
- 底面半径
- 这样根据
得到一个关于 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;
}