题目地址: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);
}
}