HDU 4617 Weapon 三维计算几何

题意:给你一些无限长的圆柱,知道圆柱轴心直线(根据他给的三个点确定的平面求法向量即可)与半径,判断是否有圆柱相交。如果没有,输出柱面最小距离。

一共只有30个圆柱,直接暴力一下就行。

判相交/相切:空间直线距离是否小于等于两圆柱半径和
若无相交,求最小:空间直线距离-两圆柱半径和

 

  1 #include <cstdio>

  2 #include <cstdlib>

  3 #include <cstring>

  4 #include <algorithm>

  5 #include <cmath>

  6 

  7 using namespace std;

  8 

  9 const double EPS = 1e-9;

 10 const int MAXN = 40;

 11 

 12 struct Point3  //空间点

 13 {

 14     double x, y, z;

 15 };

 16 

 17 struct Line3   //空间直线

 18 {

 19     Point3 a, b;

 20 };

 21 

 22 struct plane3   //空间平面

 23 {

 24     Point3 a, b, c;

 25     plane3(){}

 26     plane3( Point3 a, Point3 b, Point3 c ):

 27     a(a), b(b), c(c) { }

 28 };

 29 

 30 struct Cylinder

 31 {

 32     Point3 center;   //圆柱轴线经过的一点

 33     Point3 a, b;     //与中心点在同一平面的两点

 34     Line3 FaXian;    //轴线

 35     double R;        //圆柱半径

 36 };

 37 

 38 Cylinder CC[MAXN];

 39 

 40 Point3 Read_Point()

 41 {

 42     Point3 p;

 43     scanf("%lf%lf%lf", &p.x, &p.y, &p.z );

 44     return p;

 45 }

 46 

 47 double dcmp( double a )

 48 {

 49     if ( fabs( a ) < EPS ) return 0;

 50     return a < 0 ? -1 : 1;

 51 }

 52 

 53 //三维叉积

 54 Point3 Cross3( Point3 u, Point3 v )

 55 {

 56     Point3 ret;

 57     ret.x = u.y * v.z - v.y * u.z;

 58     ret.y = u.z * v.x - u.x * v.z;

 59     ret.z = u.x * v.y - u.y * v.x;

 60     return ret;

 61 }

 62 

 63 //三维点积

 64 double Dot3( Point3 u, Point3 v )

 65 {

 66     return u.x * v.x + u.y * v.y + u.z * v.z;

 67 }

 68 

 69 //矢量差

 70 Point3 Subt( Point3 u, Point3 v )

 71 {

 72     Point3 ret;

 73     ret.x = u.x - v.x;

 74     ret.y = u.y - v.y;

 75     ret.z = u.z - v.z;

 76     return ret;

 77 }

 78 

 79 //取平面法向量

 80 Point3 NormalVector( plane3 s )

 81 {

 82     return Cross3( Subt( s.a, s.b ), Subt( s.b, s.c ) );

 83 }

 84 Point3 NormalVector( Point3 a, Point3 b, Point3 c )

 85 {

 86     return Cross3( Subt( a, b ), Subt( b, c ) );

 87 }

 88 

 89 //两点距离

 90 double TwoPointDistance( Point3 p1, Point3 p2 )

 91 {

 92     return sqrt( (p1.x - p2.x)*(p1.x - p2.x) + (p1.y - p2.y)*(p1.y - p2.y) + (p1.z - p2.z)*(p1.z - p2.z) );

 93 }

 94 

 95 //向量的模

 96 double VectorLenth( Point3 p )

 97 {

 98     return sqrt( p.x*p.x + p.y*p.y + p.z*p.z );

 99 }

100 

101 //空间直线距离

102 double LineToLine( Line3 u, Line3 v )

103 {

104     Point3 tmp = Cross3( Subt( u.a, u.b ), Subt( v.a, v.b ) );

105     return fabs( Dot3( Subt(u.a, v.a), tmp ) ) / VectorLenth(tmp);

106 }

107 

108 int N;

109 

110 int main()

111 {

112     int T;

113     scanf( "%d", &T );

114     while ( T-- )

115     {

116         scanf( "%d", &N );

117         for ( int i = 0; i < N; ++i )

118         {

119             CC[i].center = Read_Point();

120             CC[i].a = Read_Point();

121             CC[i].b = Read_Point();

122             CC[i].R = VectorLenth( Subt( CC[i].a, CC[i].center ) );

123             CC[i].FaXian.a = CC[i].center;

124             CC[i].FaXian.b = Subt( CC[i].center, NormalVector( CC[i].center, CC[i].a, CC[i].b ) );

125         }

126 

127         bool ok = true;

128         double MinAns = 1e200;

129         for ( int i = 0; ok && i < N; ++i )

130         for ( int j = i + 1; ok && j < N; ++j )

131         {

132             double tmp = LineToLine( CC[i].FaXian, CC[j].FaXian );

133             if ( dcmp( tmp - ( CC[i].R + CC[j].R ) ) <= 0 )

134             {

135                 ok = false;

136                 break;

137             }

138             MinAns = min( MinAns, tmp - ( CC[i].R + CC[j].R ) );

139         }

140 

141         if ( ok ) printf( "%.2f\n", MinAns );

142         else puts("Lucky");

143     }

144     return 0;

145 }

 

你可能感兴趣的:(HDU)