2013杭州网络预选赛 1004 Save Labman No.004 求异面直线之间距离

题目地址:http://acm.hdu.edu.cn/showproblem.php?pid=4741

题目大意  给你4个点 确定两条异面直线,求他们之间的距离和公垂线段的垂足。


这里从twj1993那学的用直线参数方程+偏导数的方法,甚至可以解决n维坐标下的问题。


设第一条直线的参数方程是x=x1+(x3-x1)*t1 ,  y=...,z=.....    第二条直线的参数方程同理可设(t2为参数)。


然后两点之间的距离就可以表示为t1,t2的二元函数,令偏导为0就可以了。


为了方便起见,变量用x,y代替。


然后求函数系数的时候发现x,y是对称的,只需要把x改成y,z加上去就可以了


最后,很关键的一点,double 会wa的,只有输入输出的时候可以用double ,其余要用long double 


代码:

#include<iostream>
#include<cstdio>
#include<cmath>
using namespace std;

long double det2(long double a11,long double a12,long double a21,long double a22)
{
   return a11*a22-a12*a21;
}


int main()
{
  double p[12];

  long double x1,y1,z1,x2,y2,z2,x3,y3,z3,x4,y4,z4;
  long double A,B,C,D,E;

  long double DD;
  long double Dx,Dy,x,y;
  double p1x,p1y,p1z,p2x,p2y,p2z;

  long double distance;

  int T;
  cin>>T;
  while(T--)
  {

     for(int i=0;i<12;i++)
      scanf("%lf",&p[i]);


     x1=p[0];
     y1=p[1];
     z1=p[2];

     x2=p[3];
     y2=p[4];
     z2=p[5];

     x3=p[6];
     y3=p[7];
     z3=p[8];

     x4=p[9];
     y4=p[10];
     z4=p[11];

     A=(x2-x1)*(x2-x1)+(y2-y1)*(y2-y1)+(z2-z1)*(z2-z1);

     B=(x4-x3)*(x4-x3)+(y4-y3)*(y4-y3)+(z4-z3)*(z4-z3);

     C=-2*(x2-x1)*(x4-x3)-2*(y2-y1)*(y4-y3)-2*(z2-z1)*(z4-z3);

     D=2*(y2-y1)*(y1-y3)+2*(x2-x1)*(x1-x3)+2*(z2-z1)*(z1-z3);

     E=-2*(x4-x3)*(x1-x3)-2*(y1-y3)*(y4-y3)-2*(z1-z3)*(z4-z3);


     DD=det2(2*A,C,C,2*B);
     Dx=det2(-D,C,-E,2*B);
     Dy=det2(2*A,-D,C,-E);



     x=Dx/DD;
     y=Dy/DD;

     p1x=x1+(x2-x1)*x;
     p1y=y1+(y2-y1)*x;
     p1z=z1+(z2-z1)*x;

     p2x=x3+(x4-x3)*y;
     p2y=y3+(y4-y3)*y;
     p2z=z3+(z4-z3)*y;

    // cout<<p1x<<" "<<p2y<<" "<<p2x<<" "<<p2y<<endl;
     long double distance=(p1x-p2x)*(p1x-p2x)+(p1y-p2y)*(p1y-p2y)+(p1z-p2z)*(p1z-p2z);
     distance=sqrt(distance);
     double ans=distance;
     printf("%.6lf\n",ans);

     printf("%.6lf %.6lf %.6lf %.6lf %.6lf %.6lf\n",p1x,p1y,p1z,p2x,p2y,p2z);

}

}


posted @ 2013-09-16 22:13  814jingqi  阅读(179)  评论(0编辑  收藏  举报