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.
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.
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.
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
题意:求两条异面直线的最短距离以及两个坐标。
思路:这个需要一定的空间立体几何知识。今天太累了,电脑上没有好的画图工具,自带的画起来费劲又难看就不画了,直接文字描述吧。
任何两条异面直线可以转化成包含该直线的两个平行平面。这两个平行平面的距离就是最短距离,这一问就很容易理解了,也很好求。
利用两条直线的方向向量和其中一个坐标,就能这两个平行平面的法向量,即两个平面的方程。利用距离公式,距离也就求出来了。
下面来求坐标。再作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;
}