HDU 4617 Weapon 解题报告

比赛

题目

题意:给出空间中n个圆,院由圆心和圆上两点确定,且三点不共线,圆可以往两面延伸形成无限长的圆柱。问是否有圆柱相交,如果不相交,输出最短距离。

解法:用叉积求出所有圆柱轴线,然后计算直线间的距离是否大于两个圆柱半径之和来判断。听说可以用纯数学的方法,但我不会。

//time:15MS	
//memory:288K
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <iostream>
using namespace std;
const double EPS = 1e-8;
const int MAXN = 505;
int dcmp(double x)
{
    if(fabs(x)<EPS) return 0;
    return x<0? -1:1;
}
struct Point3{
    double x,y,z;
    Point3(){}
    Point3(double a,double b,double c):x(a),y(b),z(c){}
    Point3 operator+(const Point3 &a)const
    {
        return Point3(x+a.x,y+a.y,z+a.z);
    }
    Point3 operator-(const Point3 &a)const
    {
        return Point3(x-a.x,y-a.y,z-a.z);
    }
    Point3 operator*(double c)const
    {
        return Point3(x*c,y*c,z*c);
    }
    void input(){scanf("%lf%lf%lf",&x,&y,&z);}
    void output(){printf("%lf %lf %lf",x,y,z);}
};
typedef Point3 Vector3;
struct Line{
    Point3 a,b;
    double r;
};
Vector3 Cross(Vector3 a,Vector3 b)
{
    return Vector3(a.y*b.z-a.z*b.y,a.z*b.x-a.x*b.z,a.x*b.y-a.y*b.x);
}
double Dot(Vector3 a,Vector3 b)
{
    return a.x*b.x+a.y*b.y+a.z*b.z;
}
double Length(Vector3 a)
{
    return sqrt(Dot(a,a));
}
double Distoplane(Point3 p, Point3 p0, Vector3 n)
{
    return fabs(Dot(p-p0,n)/Length(n));
}
double Distoline(Point3 p, Point3 a, Point3 b)
{
    Vector3 v1 = b-a,v2 = p-a;
    return Length(Cross(v1,v2))/Length(v1);
}
double Dislinetoline(Point3 a, Point3 b, Point3 c, Point3 d)
{
    Vector3 n = Cross(a-b,c-d);
     if(dcmp(Length(n))==0)
        return Distoline(b,c,d);
    else
        return Distoplane(a,c,n);
}
int main()
{
    //freopen("/home/qitaishui/code/in.txt","r",stdin);
    int cas,n;
    Line l[35];
    Point3 a,b,c;
    Vector3 v;
    scanf("%d",&cas);
    while(cas--)
    {
        scanf("%d",&n);
        for(int i = 0; i < n; i++)
        {
            a.input(),b.input(),c.input();
            l[i].r = Length(a-b);
            l[i].a = a;
            v = Cross(b-a,c-a);
            l[i].b = a+v;
        }
        bool flag = 1;
        double ans = 1e300,tmp;
        for(int i = 0; i < n&&flag; i++)
            for(int j = i+1; j < n&&flag; j++)
            {
                tmp = Dislinetoline(l[i].a,l[i].b,l[j].a,l[j].b);
                //cout<<tmp<<" "<<l[i].r+l[j].r<<endl;
                if(dcmp(tmp-l[i].r-l[j].r)<=0) flag = 0;
                else ans = min(ans,tmp-l[i].r-l[j].r);
            }
        if(!flag) printf("Lucky\n");
        else printf("%.2f\n",ans);
    }
    return 0;
}


你可能感兴趣的:(HDU 4617 Weapon 解题报告)