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





發佈了41 篇原創文章 · 獲贊 17 · 訪問量 4萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章