UVa 1473

把所有的点都映射到XOZ这个平面的第一象限内,则这个三维问题可以转化二维问题:

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

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

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

 1 #include <cstdio>
 2 #include <cstring>
 3 #include <cstdlib>
 4 #include <cmath>
 5 #include <algorithm>
 6 
 7 #define EPS 1e-9
 8 
 9 using namespace std;
10 
11 const int MAXN = 10010;
12 const double PI = acos(-1.0);
13 
14 struct point
15 {
16     double x, y;
17 };
18 
19 int N;
20 point P[MAXN];
21 
22 int dcmp( double a )
23 {
24     if ( fabs(a) < EPS ) return 0;
25     return a < 0 ? -1 : 1;
26 }
27 
28 double GetH( double R )
29 {
30     double maxH = 0.0;
31     for ( int i = 0; i < N; ++i )
32     {
33         double tmp = R * P[i].y / ( R - P[i].x );
34         if ( dcmp( tmp - maxH ) > 0 ) maxH = tmp;
35     }
36     return maxH;
37 }
38 
39 int main()
40 {
41     while ( ~scanf( "%d", &N ) )
42     {
43         double maxR = 0.0;
44         for ( int i = 0; i < N; ++i )
45         {
46             double x, y, z;
47             scanf( "%lf%lf%lf", &x, &y, &z );
48             P[i].x = sqrt( x*x + y*y );
49             P[i].y = z;
50             maxR = max( maxR, P[i].x );
51         }
52 
53         double low = maxR, high = 1e10;
54 
55         while ( dcmp( high - low ) > 0 )
56         {
57             double mid = ( low + high ) / 2.0;
58             double midmid = ( mid + high ) / 2.0;
59 
60             double midV = GetH( mid ) * mid * mid;
61             double midmidV = GetH( midmid ) * midmid * midmid;
62 
63             if ( dcmp( midV - midmidV ) <= 0 ) high = midmid;
64             else low = mid;
65         }
66 
67         printf("%.3f %.3f
", GetH(low), low );
68     }
69     return 0;
70 }
原文地址:https://www.cnblogs.com/GBRgbr/p/3202668.html