SaveLabmanNo.004

杭州区的网络赛,求异面直线的最短距离,及公垂线与两条直线的交点坐标,这题开始直接用公式计算WA了无数次, 如果直接用公式计算,改用用long double保存中间计算结果,可以Accept.

下面贴的是一个向量法的代码

#include<cstdio>
#include<cstring>
#include<cmath>
#define eps (1e-10);
struct point{
double x,y,z;
};
double dot3(point a,point b){
    return a.x*b.x+a.y*b.y+a.z*b.z;
}
point cross3(point a,point b){
    point ret;
    ret.x=a.y*b.z-a.z*b.y;
    ret.y=a.z*b.x-b.z*a.x;
    ret.z=a.x*b.y-b.x*a.y;
    return ret;
}
point vvv(point a,point b){
    point ret;
    ret.x=a.x-b.x;
    ret.y=a.y-b.y;
    ret.z=a.z-b.z;
    return ret;
}
double dis3(point a,point b){
    double x=a.x-b.x;
    double y=a.y-b.y;
    double z=a.z-b.z;
    return sqrt(x*x+y*y+z*z);
}
double mo(point a){
    return sqrt(a.x*a.x+a.y*a.y+a.z*a.z);
}
int main(){
    point a,b,c,d;
    int ca;
    scanf("%d",&ca);
    while(ca--){
        point v;//公垂线
        point vl1,vl2,tv;
        point m;//面的法向量
        scanf("%lf%lf%lf%lf%lf%lf",&a.x,&a.y,&a.z,&b.x,&b.y,&b.z);
        scanf("%lf%lf%lf%lf%lf%lf",&c.x,&c.y,&c.z,&d.x,&d.y,&d.z);
        vl1=vvv(a,b);
        vl2=vvv(c,d);
        v=cross3(vl1,vl2);//求公垂线方向向量
        m=cross3(v,vl1);//ab与公垂线的所成面的法向量
        tv=vvv(a,c);//ab为平面内直线
        double mydis=fabs(dot3(v,tv))/mo(v);

        double t=dot3(m,tv)/dot3(m,vl2);
        double x1=c.x+vl2.x*t;
        double y1=c.y+vl2.y*t;
        double z1=c.z+vl2.z*t;

        tv=vvv(c,a);
        m=cross3(v,vl2);
        t=dot3(m,tv)/dot3(m,vl1);
        double x2=a.x+vl1.x*t;
        double y2=a.y+vl1.y*t;
        double z2=a.z+vl1.z*t;

        printf("%.6lf\n",mydis);
        printf("%.6lf %.6lf %.6lf %.6lf %.6lf %.6lf\n",x2,y2,z2,x1,y1,z1);
    }
}