题意:给你一些无限长的圆柱,知道圆柱轴心直线(根据他给的三个点确定的平面求法向量即可)与半径,判断是否有圆柱相交。如果没有,输出柱面最小距离。
一共只有30个圆柱,直接暴力一下就行。
判相交/相切:空间直线距离是否小于等于两圆柱半径和
若无相交,求最小:空间直线距离-两圆柱半径和
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <algorithm>
#include <cmath> using namespace std; const double EPS = 1e-;
const int MAXN = ; struct Point3 //空间点
{
double x, y, z;
}; struct Line3 //空间直线
{
Point3 a, b;
}; struct plane3 //空间平面
{
Point3 a, b, c;
plane3(){}
plane3( Point3 a, Point3 b, Point3 c ):
a(a), b(b), c(c) { }
}; struct Cylinder
{
Point3 center; //圆柱轴线经过的一点
Point3 a, b; //与中心点在同一平面的两点
Line3 FaXian; //轴线
double R; //圆柱半径
}; Cylinder CC[MAXN]; Point3 Read_Point()
{
Point3 p;
scanf("%lf%lf%lf", &p.x, &p.y, &p.z );
return p;
} double dcmp( double a )
{
if ( fabs( a ) < EPS ) return ;
return a < ? - : ;
} //三维叉积
Point3 Cross3( Point3 u, Point3 v )
{
Point3 ret;
ret.x = u.y * v.z - v.y * u.z;
ret.y = u.z * v.x - u.x * v.z;
ret.z = u.x * v.y - u.y * v.x;
return ret;
} //三维点积
double Dot3( Point3 u, Point3 v )
{
return u.x * v.x + u.y * v.y + u.z * v.z;
} //矢量差
Point3 Subt( Point3 u, Point3 v )
{
Point3 ret;
ret.x = u.x - v.x;
ret.y = u.y - v.y;
ret.z = u.z - v.z;
return ret;
} //取平面法向量
Point3 NormalVector( plane3 s )
{
return Cross3( Subt( s.a, s.b ), Subt( s.b, s.c ) );
}
Point3 NormalVector( Point3 a, Point3 b, Point3 c )
{
return Cross3( Subt( a, b ), Subt( b, c ) );
} //两点距离
double TwoPointDistance( Point3 p1, Point3 p2 )
{
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) );
} //向量的模
double VectorLenth( Point3 p )
{
return sqrt( p.x*p.x + p.y*p.y + p.z*p.z );
} //空间直线距离
double LineToLine( Line3 u, Line3 v )
{
Point3 tmp = Cross3( Subt( u.a, u.b ), Subt( v.a, v.b ) );
return fabs( Dot3( Subt(u.a, v.a), tmp ) ) / VectorLenth(tmp);
} int N; int main()
{
int T;
scanf( "%d", &T );
while ( T-- )
{
scanf( "%d", &N );
for ( int i = ; i < N; ++i )
{
CC[i].center = Read_Point();
CC[i].a = Read_Point();
CC[i].b = Read_Point();
CC[i].R = VectorLenth( Subt( CC[i].a, CC[i].center ) );
CC[i].FaXian.a = CC[i].center;
CC[i].FaXian.b = Subt( CC[i].center, NormalVector( CC[i].center, CC[i].a, CC[i].b ) );
} bool ok = true;
double MinAns = 1e200;
for ( int i = ; ok && i < N; ++i )
for ( int j = i + ; ok && j < N; ++j )
{
double tmp = LineToLine( CC[i].FaXian, CC[j].FaXian );
if ( dcmp( tmp - ( CC[i].R + CC[j].R ) ) <= )
{
ok = false;
break;
}
MinAns = min( MinAns, tmp - ( CC[i].R + CC[j].R ) );
} if ( ok ) printf( "%.2f\n", MinAns );
else puts("Lucky");
}
return ;
}