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
", MinAns );
142         else puts("Lucky");
143     }
144     return 0;
145 }
原文地址:https://www.cnblogs.com/GBRgbr/p/3217875.html