zoukankan      html  css  js  c++  java
  • hdu 4617 : Weapon

    Weapon

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

    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
     
    Recommend
    zhuyuanchen520
     

    算法:

    题目意思:

    D博士发明了一个新武器,要对它进行威力测试。可以威力测试的条件是圆形炮筒两端发出的射线构成无限长的圆柱,若有两个圆柱相交后相切,则可以测试,输出“Lucky”否则输出圆柱间的最短距离。

    算法思想:

    计算几何问题,将圆柱的中轴线为参考线,利用空间两条直线的距离公式

    |AB*n|/|n|,AB代表两条中轴线的两点构成的向量,这里是两个圆的圆心连线形成的向量。

    n代表法线向量,即公垂线所在的向量。n向量可以通过两圆的垂线的叉积得到。


    AB*n
    ABn的内积。

    代码:

    #include <iostream>
    #include <cstdio>
    #include <cmath>
    using namespace std;
    struct node
    {
        double x,y,z;
        double a_x,a_y,a_z;
        double b_x,b_y,b_z;
        double n_x,n_y,n_z;
        double r;
    } Cir[40];
    
    double fa_x,fa_y,fa_z,AB_x,AB_y,AB_z;
    const double MAX=1e9;
    double getDist(node A,node B)
    {
        double len_fa,len_she;
    
        //法向量
        fa_x=A.n_y*B.n_z-A.n_z*B.n_y;
        fa_y=-A.n_x*B.n_z+A.n_z*B.n_x;
        fa_z=A.n_x*B.n_y-A.n_y*B.n_x;
        len_fa=sqrt(fa_x*fa_x+fa_y*fa_y+fa_z*fa_z);
    
        //AB向量
        AB_x=A.x-B.x;
        AB_y=A.y-B.y;
        AB_z=A.z-B.z;
        len_she=fabs(AB_x*fa_x+AB_y*fa_y+AB_z*fa_z);
    
        return len_she/len_fa;
    }
    int main()
    {
        int t,n,i;
        cin>>t;
        while(t--)
        {
            cin>>n;
            for(i=0;i<n;++i)
            {
                cin>>Cir[i].x>>Cir[i].y>>Cir[i].z;
                cin>>Cir[i].a_x>>Cir[i].a_y>>Cir[i].a_z;
                cin>>Cir[i].b_x>>Cir[i].b_y>>Cir[i].b_z;
    
                Cir[i].n_x=(Cir[i].a_y-Cir[i].y)*(Cir[i].b_z-Cir[i].z)-(Cir[i].a_z-Cir[i].z)*(Cir[i].b_y-Cir[i].y);
                Cir[i].n_y=-(Cir[i].a_x-Cir[i].x)*(Cir[i].b_z-Cir[i].z)+(Cir[i].a_z-Cir[i].z)*(Cir[i].b_x-Cir[i].x);
                Cir[i].n_z=(Cir[i].a_x-Cir[i].x)*(Cir[i].b_y-Cir[i].y)-(Cir[i].a_y-Cir[i].y)*(Cir[i].b_x-Cir[i].x);
    
                //计算圆柱的半径
                Cir[i].r=sqrt((Cir[i].x-Cir[i].a_x)*(Cir[i].x-Cir[i].a_x)+(Cir[i].y-Cir[i].a_y)*(Cir[i].y-Cir[i].a_y)+(Cir[i].z-Cir[i].a_z)*(Cir[i].z-Cir[i].a_z));
            }
    
            int flag=1,j;
            double dist,ans=MAX;
            //遍历
            for(i=0;i<n-1 && flag;++i)
            {
                for(j=i+1;j<n;++j)
                {
                    dist=getDist(Cir[i],Cir[j]);//计算两个圆柱的距离
                    //cout<<dist-(Cir[i].r+Cir[j].r)<<endl;
                    ans=min(dist-(Cir[i].r+Cir[j].r),ans);
                    if(ans<=0)
                    {
                        flag=0;
                        break;
                    }
                }
    
            }
            if(flag)
            {
                printf("%.2lf
    ",ans);
            }
            else
            {
                cout<<"Lucky"<<endl;
            }
        }
        return 0;
    }
    



     

  • 相关阅读:
    常系数齐次线性递推
    【CF961G】Partitions(第二类斯特林数)
    【CF715E】Complete the Permutations(容斥,第一类斯特林数)
    【BZOJ4671】异或图(斯特林反演)
    【CF960G】Bandit Blues(第一类斯特林数,FFT)
    【BZOJ2159】Crash的文明世界(第二类斯特林数,动态规划)
    【LOJ#6374】网格(二项式反演,容斥)
    组合计数和反演
    有标号的DAG计数(FFT)
    [复习]多项式和生成函数相关内容
  • 原文地址:https://www.cnblogs.com/keanuyaoo/p/3268598.html
Copyright © 2011-2022 走看看