HDU 4617 Weapon (简单三维计算几何,异面直线距离)

Weapon

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

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
2013 Multi-University Training Contest 2  

 

Recommend zhuyuanchen520  

 

题目意思自己理解吧。

相当于给了很多圆柱面,给的三个点是垂直界面上的点,一个是圆心,另外两个是圆上的两个点。

圆柱面无线长的。

求这些圆柱面上点的最小值,有相交输出Lucky

 

这样相等于求中间那条轴线的距离。

 

求异面直线距离。感觉轴平行的时候不好处理。。。

随便搞了下就可以AC了

数据比较水吧

#include <stdio.h>
#include <algorithm>
#include <iostream>
#include <string.h>
#include <set>
#include <map>
#include <vector>
#include <queue>
#include <string>
#include <math.h>
using namespace std;
const double eps = 1e-8;
int sgn(double x)
{
    if(fabs(x) < eps)return 0;
    if(x < 0)return -1;
    else return 1;
}
struct Point3D
{
    double x,y,z;
    Point3D(double _x = 0,double _y = 0,double _z = 0)
    {
        x = _x;
        y = _y;
        z = _z;
    }
    Point3D operator -(const Point3D &b)const
    {
        return Point3D(x-b.x,y-b.y,z-b.z);
    }
    Point3D operator ^(const Point3D &b)const
    {
        return Point3D(y*b.z-z*b.y,z*b.x-x*b.z,x*b.y-y*b.x);
    }
    double operator *(const Point3D &b)const
    {
        return x*b.x+y*b.y+z*b.z;
    }
    void input()
    {
        scanf("%lf%lf%lf",&x,&y,&z);
    }
};
double Norm(Point3D p)
{
    return sqrt(p*p);
}
//计算两个异面直线的距离
//第一条直线过点a,方向向量为k1,第二条直线过点
double calc(Point3D a,Point3D k1,Point3D b,Point3D k2)
{
    Point3D tmp = k1^k2;
    return fabs(tmp*(a-b))/sqrt(tmp*tmp);
}

struct Node
{
    Point3D o,p1,p2;
    void input()
    {
        o.input();
        p1.input();
        p2.input();
    }
}node[50];

int main()
{
    //freopen("in.txt","r",stdin);
    //freopen("out.txt","w",stdout);
    int T;
    int n;
    scanf("%d",&T);
    while(T--)
    {
        scanf("%d",&n);
        for(int i = 0;i < n;i++)
            node[i].input();
        bool flag = false;
        double Min = 1e20;
        for(int i = 0;i < n;i++)
            for(int j = i+1;j < n;j++)
            {
                if(flag)break;
                double  r1 = sqrt((node[i].p1-node[i].o)*(node[i].p1-node[i].o));
                double  r2 = sqrt((node[j].p1-node[j].o)*(node[j].p1-node[j].o));
                Point3D  k1 = (node[i].p1-node[i].o)^(node[i].p2-node[i].o);
                Point3D  k2 = (node[j].p1-node[j].o)^(node[j].p2-node[j].o);
                if(sgn(Norm(k1^k2))==0)
                {
                    if(sgn( Norm( k1^(node[i].o-node[j].o)) ) == 0)//同轴
                    {
                        if(sgn(r1-r2) == 0)
                        {
                            flag = true;
                            break;
                        }
                        else continue;
                    }
                    else
                    {
                        double dd = (k1*(node[i].o-node[j].o))/Norm(k1);
                        double d = sqrt( Norm(node[i].o-node[j].o)*Norm(node[i].o-node[j].o) - dd*dd );
                        if(d > fabs(r1-r2) &&d < fabs(r1+r2))
                        {
                            flag = true;
                            break;
                        }
                        Min = min(Min,d-r1-r2);
                    }
                    continue;
                }
                double d = calc(node[i].o,k1,node[j].o,k2);
                if(d < r1 + r2 -eps)
                {
                    flag = true;
                    break;
                }
                Min = min(Min,d-r1-r2);
            }
        if(flag || sgn(Min)<=0)printf("Lucky\n");
        else printf("%.2lf\n",Min);
    }
    return 0;
}

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

    原文作者:算法小白
    原文地址: https://www.cnblogs.com/kuangbin/p/3215317.html
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞