您的位置:首页 > 其它

UVa 1473 - Dome of Circus 三分

2013-07-20 17:37 197 查看
把所有的点都映射到XOZ这个平面的第一象限内,则这个三维问题可以转化二维问题:

求一条直线,使所有点在这条直线的下方,直线与X轴和Z轴围成的三角形旋转形成的圆锥体积最小。

这样转化之后可以看出直线的临界条件应当是经过其中一点。

三分圆锥半径R,因为要覆盖所有的点,让点(R, 0)与所有点连线,直线与Z轴交点即为H,H取其中最大的那个。

#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <cmath>
#include <algorithm>

#define EPS 1e-9

using namespace std;

const int MAXN = 10010;
const double PI = acos(-1.0);

struct point
{
double x, y;
};

int N;
point P[MAXN];

int dcmp( double a )
{
if ( fabs(a) < EPS ) return 0;
return a < 0 ? -1 : 1;
}

double GetH( double R )
{
double maxH = 0.0;
for ( int i = 0; i < N; ++i )
{
double tmp = R * P[i].y / ( R - P[i].x );
if ( dcmp( tmp - maxH ) > 0 ) maxH = tmp;
}
return maxH;
}

int main()
{
while ( ~scanf( "%d", &N ) )
{
double maxR = 0.0;
for ( int i = 0; i < N; ++i )
{
double x, y, z;
scanf( "%lf%lf%lf", &x, &y, &z );
P[i].x = sqrt( x*x + y*y );
P[i].y = z;
maxR = max( maxR, P[i].x );
}

double low = maxR, high = 1e10;

while ( dcmp( high - low ) > 0 )
{
double mid = ( low + high ) / 2.0;
double midmid = ( mid + high ) / 2.0;

double midV = GetH( mid ) * mid * mid;
double midmidV = GetH( midmid ) * midmid * midmid;

if ( dcmp( midV - midmidV ) <= 0 ) high = midmid;
else low = mid;
}

printf("%.3f %.3f\n", GetH(low), low );
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: