题意:给若干无限长的圆柱,知道圆柱轴心上的一个点和同平面上的另外两个点,还有半径,判断是否有圆柱相交,不相交则输出最小距离。

思路:由于已知同平面上的三个点,其中一个点还是轴线上的点,所以可以确定出一个平面,然后求出法向量,法向量和轴心上的点就可以确定出轴心直线了。然后计算任意两条空间直线间的距离,由于只有30个圆柱,暴力嘛,用距离减去两圆柱的半径和,小于等于0则相交,大于0就不相交。空间直线的距离d=|AB*n| / |n| (AB表示异面直线任意2点的连线,n表示法向量,法向量为两条异面直线方向向量的叉积,|n|表示模。

#include<iostream>
#include<vector>
#include<queue>
#include<cstring>
#include<cstdio>
#include<algorithm>
#include<cmath>
using namespace std;
const int maxn=35;
const double eps=1e-8;
struct Point3
{
    double x,y,z;
    Point3(double x=0,double y=0,double z=0):x(x),y(y),z(z){}
}a[maxn],b[maxn],c[maxn],v[maxn];
double r[maxn];
typedef Point3 Vector3;
Vector3 operator + (Vector3 A,Vector3 B)
{
    return Vector3(A.x+B.x,A.y+B.y,A.z+B.z);
}
Vector3 operator - (Vector3 A,Vector3 B)
{
    return Vector3(A.x-B.x,A.y-B.y,A.z-B.z);
}
int dcmp(double x)
{
    if(fabs(x)<eps) return 0;
    else return x<0?-1:1;
}
double Dot3(Vector3 A,Vector3 B)
{
    return A.x*B.x+A.y*B.y+A.z*B.z;
}
double Length3(Vector3 A)
{
    return sqrt(Dot3(A,A));
}
Vector3 Cross(Vector3 A,Vector3 B)
{
    return Vector3(A.y*B.z-A.z*B.y,A.z*B.x-A.x*B.z,A.x*B.y-A.y*B.x);
}
double dis(Point3 a,Point3 b,Vector3 v)
{
    Vector3 p=a-b;
    return fabs(Dot3(p,v))/Length3(v);
}
int main()

{
    int t,n;
    scanf("%d",&t);
    while(t--)
    {
        scanf("%d",&n);
        for(int i=0;i<n;i++)
        {
            scanf("%lf%lf%lf%lf%lf%lf%lf%lf%lf",&a[i].x,&a[i].y,
            &a[i].z,&b[i].x,&b[i].y,&b[i].z,&c[i].x,&c[i].y,&c[i].z);
            v[i]=Cross(b[i]-a[i],c[i]-a[i]);
            r[i]=Length3(b[i]-a[i]);
} int k=0; double ans,minm=1e9; for(int i=0;i<n;i++) { for(int j=i+1;j<n;j++) { Vector3 v1=Cross(v[i],v[j]); double ans=dis(a[i],a[j],v1)-r[i]-r[j]; if(ans<0 || dcmp(ans)==0) { k=1;break; } else { minm=min(ans,minm); } } if(k==1) break; } if(k==1) printf("Lucky\n"); else printf("%.2lf\n",minm); } return 0; }

 

 posted on 2013-08-08 21:48  ∑求和  阅读(320)  评论(0编辑  收藏  举报