HDU 4741 Save Labman No.004 2013 ACM/ICPC Asia Regional Hangzhou Online



Save Labman No.004

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 1575    Accepted Submission(s): 520


Problem Description
Due to the preeminent research conducted by Dr. Kyouma, human beings have a breakthrough in the understanding of time and universe. According to the research, the universe in common sense is not the only one. Multi World Line is running simultaneously. In simplicity, let us use a straight line in three-dimensional coordinate system to indicate a single World Line.

During the research in World Line Alpha, the assistant of Dr. Kyouma, also the Labman No.004, Christina dies. Dr. Kyouma wants to save his assistant. Thus, he has to build a Time Tunnel to jump from World Line Alpha to World Line Beta in which Christina can be saved. More specifically, a Time Tunnel is a line connecting World Line Alpha and World Line Beta. In order to minimizing the risks, Dr. Kyouma wants you, Labman No.003 to build a Time Tunnel with shortest length.
 

Input
The first line contains an integer T, indicating the number of test cases.

Each case contains only one line with 12 float numbers (x1, y1, z1), (x2, y2, z2), (x3, y3, z3), (x4, y4, z4), correspondingly indicating two points in World Line Alpha and World Line Beta. Note that a World Line is a three-dimensional line with infinite length.

Data satisfy T <= 10000, |x, y, z| <= 10,000.
 

Output
For each test case, please print two lines.

The first line contains one float number, indicating the length of best Time Tunnel.

The second line contains 6 float numbers (xa, ya, za), (xb, yb, zb), seperated by blank, correspondingly indicating the endpoints of the best Time Tunnel in World Line Alpha and World Line Beta.

All the output float number should be round to 6 digits after decimal point. Test cases guarantee the uniqueness of the best Time Tunnel.
 

Sample Input
  
  
1 1 0 1 0 1 1 0 0 0 1 1 1
 

Sample Output
  
  
0.408248 0.500000 0.500000 1.000000 0.666667 0.666667 0.666667
 

Source
 

Recommend
liuyiding   |   We have carefully selected several similar problems for you:   5061  5060  5059  5058  5057 


题意:求两条异面直线的最短距离以及两个坐标。

思路:这个需要一定的空间立体几何知识。今天太累了,电脑上没有好的画图工具,自带的画起来费劲又难看就不画了,直接文字描述吧。

   任何两条异面直线可以转化成包含该直线的两个平行平面。这两个平行平面的距离就是最短距离,这一问就很容易理解了,也很好求。
利用两条直线的方向向量和其中一个坐标,就能这两个平行平面的法向量,即两个平面的方程。利用距离公式,距离也就求出来了。
下面来求坐标。再作2个平面,分别作过两条直线且垂直于两平行平面的两个平面。再利用直线的方向向量和平行平面的法向量可以求出这两个平面的方程。
这两个方程分别和另外的直线(也就是两条直线中不在平面内的直线)交点,即为所求坐标。(证明略,自己看立体几何吧)

AC代码:

#include<stdio.h>
#include<math.h>

double pa,pb,pc,a,b,c;//法向量; 

double fabs(double x)
{
   if(x<0)
   return -x;
   return x;
} 

//一直两个不平行的向量,求垂直这两个向量的向量;
//即解方程组 a1*x+b1*y+c1*z=0和 a2*x+b2*y+c2*z=0;
//得到向量 a,b,c; 
void cal(double a1,double b1,double c1,double a2,double b2,double c2)
{
   double t1,t2;
   t1=a1*b2-a2*b1;
   t2=b1*c2-b2*c1;
   if(t1==0.0&&t2!=0.0)
   {
      a=1;
      c=0;
      if(b1==0.0)
      b=1;
      else
      b=-a1/b1;
   }
   else if(t1!=0.0&&t2==0.0)
   {
      c=1;
      a=0;
      if(b1==0.0)
      b=1;
      else
      b=-c1/b1;
   }
   else if(t1!=0.0&&t2!=0.0)
   {
      a=1;
      c=t1/t2;
      if(b1==0.0)
      b=1;
      else
      b=(a2*c1-a1*c2)/t2;
   }
   else if(t1==0.0&&t2==0.0)
   {
      c=1;
      a=1;
      if(b1==0.0)
      b=1;
      else
      b=-(a1+c1)/b1;
   }
}

int main()
{
   int T;
   double x1,y1,z1,x2,y2,z2,x3,y3,z3,x4,y4,z4;//输入四个点; 
   double xa,ya,za,xb,yb,zb;//最近的两个点; 
   double a1,b1,c1,a2,b2,c2;//两条直线的方向向量; 
   double t,d;
   scanf("%d",&T);
   while(T--)
   {
      scanf("%lf%lf%lf%lf%lf%lf%lf%lf%lf%lf%lf%lf",&x1,&y1,&z1,&x2,&y2,&z2,&x3,&y3,&z3,&x4,&y4,&z4);
      a1=x2-x1;
      b1=y2-y1;
      c1=z2-z1;
      a2=x4-x3;
      b2=y4-y3;
      c2=z4-z3;
      cal(a1,b1,c1,a2,b2,c2);
      t=(a*x1+b*y1+c*z1)-(a*x3+b*y3+c*z3);
      d=fabs(t)/sqrt(a*a+b*b+c*c);  //求距离; 
      printf("%lf\n",d);
      pa=a;
      pb=b;
      pc=c;
      //其中一个坐标; 
      cal(pa,pb,pc,a1,b1,c1);//计算一个平面的法向量; 
      t=(a*(x1-x3)+b*(y1-y3)+c*(z1-z3))/(a*a2+b*b2+c*c2);
      xa=t*a2+x3;
      ya=t*b2+y3;
      za=t*c2+z3;
      //另一个坐标; 
      cal(pa,pb,pc,a2,b2,c2);//计算另一个平面的法向量; 
      t=(a*(x3-x1)+b*(y3-y1)+c*(z3-z1))/(a*a1+b*b1+c*c1);
      xb=t*a1+x1;
      yb=t*b1+y1;
      zb=t*c1+z1;
      printf("%lf %lf %lf %lf %lf %lf\n",xb,yb,zb,xa,ya,za);
   }
   return 0;
}


 


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值