2013杭州網路賽D題HDU 4741(計算幾何 解三元一次方程組)

果7發表於2013-09-17

Save Labman No.004

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


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
 
題目大意:當時看見這個題目蠻激動的,因為求異面直線的最短距離前不久還寫過部落格,不過那樣只能求最短距離。當時被迫與無奈。題目大意很簡單,給你兩條直線,問你最短距離是多少,並且求出最短距離的點,需要求得點是唯一的。

解題思路:當時自己想的就是先把兩條直線求出來,然後分別在兩條直線上找倆點p和q。這樣未知數就有兩個,然後再求公垂線,根據公垂線與pq共線xyz三維座標即可列出三元一次方程組,未知數三個,方程有三個。只是算起來不是很順手。詳見AC程式碼。

題目地址:Save Labman No.004

AC程式碼:
#include<iostream>
#include<cstring>
#include<cstdio>
#include<cmath>
using namespace std;

int main()
{
    int tes;
    double x1,y1,z1,x2,y2,z2,x3,y3,z3,x4,y4,z4;
    double a1,b1,c1,a2,b2,c2;
    scanf("%d",&tes);
    while(tes--)
    {
            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;  //第二條直線
            double k1,k2;
            double p1,p2,p3;  //p點
            double q1,q2,q3;  //q點
            double s1,s2,s3;  //前兩條直線的公垂線
            s1=b1*c2-b2*c1;
            s2=c1*a2-c2*a1;
            s3=a1*b2-a2*b1;
            //方程組轉化為
            //t1*k1+t2*k2=t3,m1*k1+m2*k2=m3;
            double t1,t2,t3,m1,m2,m3;
            t1=s2*a1-s1*b1,t2=s1*b2-s2*a2,t3=s1*(y1-y3)-s2*(x1-x3);
            m1=s3*a1-s1*c1,m2=s1*c2-s3*a2,m3=s1*(z1-z3)-s3*(x1-x3);
            k1=(t3*m2-m3*t2)/(t1*m2-m1*t2);
            k2=(t3*m1-m3*t1)/(t2*m1-m2*t1);

            p1=k1*a1+x1,p2=k1*b1+y1,p3=k1*c1+z1,
            q1=k2*a2+x3,q2=k2*b2+y3,q3=k2*c2+z3;
            double dis=sqrt((p1-q1)*(p1-q1)+(p2-q2)*(p2-q2)+(p3-q3)*(p3-q3));
            printf("%.6lf\n",dis);
            printf("%.6lf %.6lf %.6lf %.6lf %.6lf %.6lf\n",p1,p2,p3,q1,q2,q3);
    }
    return 0;
}

/*
23
0 0 0 0 0 1 1 0 0 0 1 0
*/
//234MS 248K


相關文章