HDU 4741 Save Labman No.004 2013 ACM/ICPC 杭州网络赛

传送门:http://acm.hdu.edu.cn/showproblem.php?pid=4741

 

题意:给你两条异面直线,然你求着两条直线的最短距离,并求出这条中垂线与两直线的交点。

需要注意的是,不知道为什么用double就WA了,但是改为long double就AC了。

 

AC代码:

#include <iostream>

#include <cstdio>

#include <cstring>

#include <string>

#include <cstdlib>

#include <cmath>

#include <vector>

#include <list>

#include <deque>

#include <queue>

#include <iterator>

#include <stack>

#include <map>

#include <set>

#include <algorithm>

#include <cctype>

using namespace std;



typedef __int64 LL;

const int N=1100;

const int INF=0x3f3f3f3f;

const long double PI=acos(-1.0);

const long double eps=1e-7;



bool zero(long double x)

{

    if(fabs(x)<eps)

        return true;

    return false;

}



struct point3D

{

    long double x,y,z;

    point3D(){};

    point3D(long double a,long double b,long double c):x(a),y(b),z(c){}

    void input()

    {

        double a,b,c;

        scanf("%lf%lf%lf",&a,&b,&c);

        x=a,    y=b,    z=c;

    }

    friend point3D operator -(const point3D &a,const point3D &b)

    {

        return point3D(a.x-b.x,a.y-b.y,a.z-b.z);

    }

    friend point3D operator +(const point3D &a,const point3D &b)

    {

        return point3D(a.x+b.x,a.y+b.y,a.z+b.z);

    }

};



struct line

{

    long double a,b,c,d;

    point3D u,v;

}l[33];



long double vlen(point3D a)//向量长度

{

    return sqrt(a.x*a.x+a.y*a.y+a.z*a.z);

}



long double dis(point3D a,point3D b)//两点距离

{

    long double x=a.x-b.x;

    long double y=a.y-b.y;

    long double z=a.z-b.z;

    return sqrt(x*x+y*y+z*z);

}



point3D xmult(point3D u,point3D v)//叉积,法向量

{

    point3D 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;

}



long double dmult(point3D u,point3D v)//点积

{

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

}



point3D get_faline(point3D a,point3D b,point3D c)//平面的法向量

{

    return xmult(b-a,c-a);

}



bool dian_inline(point3D a,point3D b,point3D c)//判断三点共线

{

    return vlen(xmult(b-a,c-a))<eps;

}



bool dian_inmian(point3D a,point3D b,point3D c,point3D d)//四点公面

{

    return zero(dmult(get_faline(a,b,c),d-a));

}



long double xian_xian(line l1,line l2)//直线到直线的距离

{

    point3D n=xmult(l1.u-l1.v,l2.u-l2.v);//法向量

    return fabs(dmult(l1.u-l2.u,n))/vlen(n);

}



point3D a,b,c,d;



long double F1(point3D a,point3D b)

{

    return ((b.x-a.x)*(b.x-a.x)+(b.y-a.y)*(b.y-a.y)+(b.z-a.z)*(b.z-a.z));

}



long double F2()

{

    return ((b.x-a.x)*(d.x-c.x)+(b.y-a.y)*(d.y-c.y)+(b.z-a.z)*(d.z-c.z));

}



long double F3ab(point3D a,point3D b)

{

    return ((b.x-a.x)*(c.x-a.x)+(b.y-a.y)*(c.y-a.y)+(b.z-a.z)*(c.z-a.z));

}



long double F3cd(point3D c,point3D d)

{

    return ((d.x-c.x)*(c.x-a.x)+(d.y-c.y)*(c.y-a.y)+(d.z-c.z)*(c.z-a.z));

}



int main()

{

    int T;

    cin>>T;

    while(T--)

    {

        a.input();  b.input();  c.input();  d.input();

        line l1,l2;

        l1.u=a;   l1.v=b;

        l2.u=c;   l2.v=d;

        printf("%.6lf\n",(double)xian_xian(l1,l2));

        long double x[6];

        long double xh1,xh2;

        xh1=F3ab(a,b)*F1(c,d)-F3cd(c,d)*F2();

        xh2=F1(a,b)*F1(c,d)-F2()*F2();

        x[0]=(b.x-a.x)*xh1/xh2+a.x;

        x[1]=(b.y-a.y)*xh1/xh2+a.y;

        x[2]=(b.z-a.z)*xh1/xh2+a.z;



        long double xx1,xx2,xxx;

        xx1=F3cd(c,d)*F1(a,b)-F3ab(a,b)*F2();

        xx2=F2()*F2()-F1(a,b)*F1(c,d);

        xxx=xx1/xx2;

        x[3]=(d.x-c.x)*xxx+c.x;

        x[4]=(d.y-c.y)*xxx+c.y;

        x[5]=(d.z-c.z)*xxx+c.z;



        for(int i=0;i<5;i++)

            printf("%.6lf ",(double)x[i]);

        printf("%.6lf\n",(double)x[5]);

    }

    return 0;

}


 

 

你可能感兴趣的:(ICPC)