UVa 1473 - Dome of Circus 三分

把所有的点都映射到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\n", GetH(low), low );

68     }

69     return 0;

70 }

 

你可能感兴趣的:(dom)