hdu 4741——Save Labman No.004

题意:求两个空间直线的距离,并求出这两个直线中距离最近两个点的坐标
思路:刚刚复习完高数的立体几何部分。。然后就用了在复习全书上看到的一个方法来求解。
两个向量的叉积表示得到一个垂直于这两个向量的向量,所得向量的膜是这两个向量组成平行四边形的面积。假设题目所给两个直线的方向向量是s1,s2,在两个直线上任选两点,这两点构成向量AB。
则两个直线距离就是(s1 s2 AB)的混合积除以(s1s2叉积的膜)。混合积的几何意义就是三个向量构成立方体的体积,s1s2的叉积为这个立方体的底面积。两个相除得到高,就是两个直线的距离。
这里写图片描述
求两个距离最短点的时候,我的思路是用偏导数来求,不过貌似精度不够。先写在这里。
两个直线用参数方程形式写出来,得到
L1: X1 = at+x1 Y1 = bt+y1 Z1 = ct + z1
L2:X2 = dm +x2 Y2 = em+y2 Z2 = fm+z2
其中,(a,b,c)(d,e,f)是方向向量
距离为D=(X1-X2)^2+(Y1-Y2)^2+(Z1-Z2)^2
当距离最小的时候,D对t的偏导数及D对m的偏导数都是0,最后化成解二元一次方程组。
代码如下:

#include <cstring>
#include <stdio.h>
#include <algorithm>
#include <iostream>
#include <cmath>
#include <map>
#include <string>
#include <queue>
#include <bitset>
#include<assert.h>
using namespace std;

int dcmp(double x)
{
   if(fabs(x)<1e-6)return 0;
   return x<0?-1:1;
}

struct Point
{
    double x,y,z;
    Point(double _x=0,double _y=0,double _z=0):x(_x),y(_y),z(_z){
        if(dcmp(x)==0)x=0;
        if(dcmp(y)==0)y=0;
        if(dcmp(z)==0)z=0;
    }
    void scan(){
        scanf("%lf%lf%lf",&x,&y,&z);
    }
    void p()
    {
        printf("%.6lf %.6lf %.6lf",x,y,z);
    }
};
typedef Point Vector;

Vector operator + (const Vector &a,const Vector &b){ return Vector(a.x+b.x,a.y+b.y,a.z+b.z);}
Vector operator - (const Vector &a,const Vector &b){ return Vector(a.x - b.x,a.y - b.y, a.z - b.z);}
Vector operator * (const Vector &a,const double &b){ return Vector(a.x*b,a.y*b,a.z*b);}
Vector operator / (const Vector &a,const double &b){ return Vector(a.x/b,a.y/b,a.z/b);}

double dot(const Vector &a,const Vector &b){
    return a.x*b.x+a.y*b.y+a.z*b.z;
}
double Lenth(const Vector &a)
{
    return sqrt((dot(a,a)));
}

Vector det(const Vector &a,const Vector &b)
{
    return Vector(a.y*b.z-a.z*b.y,a.z*b.x-a.x*b.z,a.x*b.y-a.y*b.x);
}



int main()
{
//    freopen("data.txt","r",stdin);
    int T;
    scanf("%d",&T);
    while(T--){
        Point a1,a2,b1,b2;
        a1.scan();a2.scan();b1.scan();b2.scan();
        Vector a = a1-a2;
        Vector b = b1-b2;
        Vector AB=b1-a1;
        double ansl=fabs(dot(det(a,b),AB))/fabs(Lenth(det(a,b)));
        printf("%.6lf\n",ansl);
        //======================/这里是我的方法
        double a11=dot(a,a);
        double a12=-(dot(a,b));
        double a21 = -dot(a,b);
        double a22 = dot(b,b);
        if(dcmp(a11)==0)a11=0;
        if(dcmp(a12)==0)a12=0;
        if(dcmp(a21)==0)a21=0;
        if(dcmp(a22)==0)a22=0;
        double c1=dot(a,AB);
        double c2 = -dot(b,AB);
        if(dcmp(c1)==0)c1=0;
        if(dcmp(c2)==0)c2=0;
        double S =a11*a22-a12*a21;

        double t = (-c1*a22+a12*c2)/S;
        double m = (-a11*c2+c1*a21)/S;
        Point ans1=a*(-t)+a1;
        Point ans2 = b*(-m)+b1;
        //=======================/
//++++++++++++++++++++++++++/参考http://blog.sina.com.cn/s/blog_a401a1ea0101ij9z.html
        double t1 = dot(det(AB,b),det(a,b));
        t1/=dot(det(a,b),det(a,b));
        double t2 = dot(det(AB,a),det(a,b));
        t2/=dot(det(a,b),det(a,b));

        Point aa=a1+(a*t1);
        Point bb = b1+(b*t2);
        aa.p();printf(" ");
        bb.p();puts("");
        Vector test1=aa-ans1;
        Vector test2=bb-ans2;
//+++++++++++++++++++     
//下面将两种方法的结果对比了一下,发现当精度在1e-6的时候两个结果是一样的,但是精度到1e-7的时候,就错了   
if(dcmp(test1.x)||dcmp(test1.y)||dcmp(test1.z))cout<<1/0;
        if(dcmp(test2.x)||dcmp(test2.y)||dcmp(test2.z))cout<<1/0;
    }
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值