• HDU 4617Weapon(两条异面直线的距离)


    Weapon

    Time Limit: 3000/1000 MS (Java/Others)    Memory Limit: 65535/32768 K (Java/Others)
    Total Submission(s): 270    Accepted Submission(s): 212

    Problem Description
    Doctor D. are researching for a horrific weapon. The muzzle of the weapon is a circle. When it fires, rays form a cylinder that runs through the circle verticality in both side. If one cylinder of rays touch another, there will be an horrific explosion. Originally, all circles can rotate easily. But for some unknown reasons they can not rotate any more. If these weapon can also make an explosion, then Doctor D. is lucky that he can also test the power of the weapon. If not, he would try to make an explosion by other means. One way is to find a medium to connect two cylinder. But he need to know the minimum length of medium he will prepare. When the medium connect the surface of the two cylinder, it may make an explosion.
     
    Input
    The first line contains an integer T, indicating the number of testcases. For each testcase, the first line contains one integer N(1 < N < 30), the number of weapons. Each of the next 3N lines&#160; contains three float numbers. Every 3 lines represent one weapon. The first line represents the coordinates of center of the circle, and the second line and the third line represent two points in the circle which surrounds the center. It is supposed that these three points are not in one straight line. All float numbers are between -1000000 to 1000000.
     
    Output
    For each testcase, if there are two cylinder can touch each other, then output 'Lucky', otherwise output then minimum distance of any two cylinders, rounded to two decimals, where distance of two cylinders is the minimum distance of any two point in the surface of two cylinders.
     
    Sample Input
    3 3 0 0 0 1 0 0 0 0 1 5 2 2 5 3 2 5 2 3 10 22 -2 11 22 -1 11 22 -3 3 0 0 0 1 0 1.5 1 0 -1.5 112 115 109 114 112 110 109 114 111 -110 -121 -130 -115 -129 -140 -104 -114 -119.801961 3 0 0 0 1 0 1.5 1 0 -1.5 112 115 109 114 112 110 109 114 111 -110 -121 -130 -120 -137 -150 -98 -107 -109.603922
     
    Sample Output
    Lucky 2.32 Lucky
     
    Source
     

                         题目大意:当时LOR做出来了之后,我就看了一下,题目在二十分钟之内读懂了。但是想复杂了,没有直接转换思路。题目给你很多无限延伸的圆柱,问你有没有相交的,有的话输出Lucky没有的话输出还差的最小距离。

                 解题思路:当时没有想到直接可以抽象成经过圆心垂直于圆面的直线的距离,再与两个半径之和相比。就好比求两个圆是否相交,只用求两个圆心之间的距离,然后与半径之和相比,是一样的思路。

                 题目地址:Weapon

    基础知识   求两条异面直线的距离


    当然求两条异面直线的距离,可以找到两条直线的公垂向量,然后在两条直线上面找两个点连成直线直接往上面射影即可。感谢程怀俊。当然这个题找点的话可以直接用开始给的圆心。

    若向量a=(a1,b1,c1),向量b=(a2,b2,c2), 则 
    向量a·向量b=a1a2+b1b2+c1c2 
    向量a×向量b=(b1c2-b2c1,c1a2-a1c2,a1b2-a2b1) 
    (i、j、k分别为空间中相互垂直的三条坐标轴的单位向量)。

    不过这个题目还debug了一下。因为两个向量 点乘的时候可能是负的,夹角大于90度的时候。所以需要转化为正。具体见代码。


    AC代码:代码配合下面图片使用

    #include<iostream>
    #include<cstring>
    #include<cstdio>
    #include<cmath>
    using namespace std;
    
    struct mq
    {
        double x;  //x,y,z表示垂直于圆表面的向量
        double y;
        double z;
        double a;  //a,b,c圆心的坐标
        double b;
        double c;
        double r;  //r圆的半径
    };
    mq node[42];
    
    double solve(mq p1,mq p2)
    {
        double a1,b1,c1,a2,b2,c2;
        double s1,s2,s3;  //s向量
        double q1,q2,q3;
        double ans1,ans2,ans;
        a1=p1.x,b1=p1.y,c1=p1.z;
        a2=p2.x,b2=p2.y,c2=p2.z;
        s1=b1*c2-b2*c1,s2=c1*a2-c2*a1;
        s3=a1*b2-a2*b1;
        q1=p2.a-p1.a,q2=p2.b-p1.b;
        q3=p2.c-p1.c;
        ans1=fabs(q1*s1+q2*s2+q3*s3);
        ans2=sqrt(s1*s1+s2*s2+s3*s3);
        ans=ans1/ans2;
        return ans;
    }
    
    int main()
    {
        int tes,n,i,j;
        double x1,y1,z1,x2,y2,z2,x3,y3,z3;
        double a1,b1,c1,a2,b2,c2;
        scanf("%d",&tes);
        while(tes--)
        {
            scanf("%d",&n);
            for(i=0;i<n;i++)
            {
                scanf("%lf%lf%lf%lf%lf%lf%lf%lf%lf",&x1,&y1,&z1,&x2,&y2,&z2,&x3,&y3,&z3);
                node[i].a=x1,node[i].b=y1,node[i].c=z1,
                a1=x2-x1,b1=y2-y1,c1=z2-z1;
                a2=x3-x1,b2=y3-y1,c2=z3-z1;
                node[i].r=sqrt(a1*a1+b1*b1+c1*c1); //半径
                node[i].x=b1*c2-b2*c1,node[i].y=c1*a2-c2*a1;
                node[i].z=a1*b2-a2*b1;
            }
    
            int flag=0;
            double res=10000000;
            double tmp;
            //tmp=solve(node[0],node[1]);
            //printf("%.2f
    ",tmp);
            for(i=0;i<n;i++)
            {
                for(j=i+1;j<n;j++)
                {
                    tmp=solve(node[i],node[j]);  //tmp返回的是两条中间的线的距离
                    tmp=tmp-node[i].r-node[j].r;
                    if(tmp<=0)
                    {
                        flag=1;
                        break;
                    }
                    if(tmp<res)
                        res=tmp;
                }
                if(flag)
                    break;
            }
            if(flag) puts("Lucky");
            else printf("%.2f
    ",res);
    
        }
        return 0;
    }
    



  • 相关阅读:
    Eclipse
    文件递归查找
    BeanFactory 和 AppliactionContext的区别?
    文件上传
    Servlet路径的使用
    FileInputStream和FileOutputStream文件复制
    CentOS 7安装Nginx
    C语言程序设计100例之(6):数字反转
    C语言程序设计100例之(5):分解质因数
    C语言程序设计100例之(4):水仙花数
  • 原文地址:https://www.cnblogs.com/pangblog/p/3283582.html
Copyright © 2020-2023  润新知