Weapon

/*

题意:求是否存在两圆柱相交, 如果不存在求最短距离.

分析:可以转化为空间直线距离问题,  然后如果距离 - 去半径和 <= 0 则相交

空间直线距离: 求两直线方向向量的确定的面的法向量n,  然后求出一条端点在不同直线上的任意向量, 最后通过点积可以求出该向量在法向量上的投影。投影的长度就是答案。 公式: dist = fas(dot(normal, anyVec) / vlen(normal));

*/

#include <iostream>
#include <cstring>
#include <string>
#include <cmath>
#include <algorithm>
#include <cstdio>
#include <cstdlib>
#include <vector>
#include <queue>
#include <deque>

#define MAX 200005
#define INF 1e8
#define FOR(i, n) for(int i  = 0; i < n; i++)
#define FORB(i, n) for(int i = n - 1; i >= 0; i--)
#define MP(i, j) make_pair(i, j)
#define MEM(array, val) memset(array, val, sizeof(array))
#define pu first
#define pv second
#define eps 1e-8
#define INF 1e50
using namespace std;
inline int cmpd(double x){ return x > eps ? 1 : ( x < - eps ? - 1 : 0); }
inline double sqr(double x){ return x * x;}
inline bool zero(double x){return cmpd(x) == 0;}
int sgn(double x){ return x > eps ? 1 : (x < -eps? -1 : 0); }
template<class T>
class Vector3d{
public :
    T x, y, z;
    Vector3d(){}
    Vector3d(const T &ix, const T &iy, const T &iz):x(ix), y(iy), z(iz){}
    //重载+ - * /
    Vector3d operator + (const Vector3d &a)const{
        return Vector3d(x + a.x, y + a.y, z + a.z);
    }
    Vector3d operator - (const Vector3d &a)const {
        return Vector3d(x - a.x, y - a.y, z - a.z);
    }
    Vector3d operator / (const T &a)const {
        return Vector3d(x / a, y / a, z / a);
    }
    Vector3d operator * (const T &a)const {
        return Vector3d(x * a, y *a,  z * a);
    }
    friend Vector3d operator * (const T &a, const Vector3d &b){
        return Vector3d(a * b.x, a * b.y, a * b.z);
    }

    ///点积
    friend T dot(const Vector3d &a, const Vector3d &b){
        return a.x * b.x + a.y * b.y + a.z * b.z;
    }
    //叉积
    friend Vector3d det(const Vector3d &a, const Vector3d &b){
        T xx = a.y * b.z - a.z * b.y;
        T yy = a.z * b.x - a.x * b.z;
        T zz = a.x * b.y - a.y * b.x;
        return Vector3d(xx, yy, zz);
    }
  
    //两点距离
    friend T dist(const Vector3d &a, const Vector3d &b){
        return (b - a).length();
    }
    //叉积结果
    friend double cross(const Vector3d &a, const Vector3d &b){
        Vector3d res = det(a, b);
        return res.x + res.y + res.z;
    }
    //向量长度
    T length()const{
        return sqrt(dot(*this, *this));
    }
    //单位向量
    Vector3d unitVec(){
        return *this / length();
    }
    //向量长度
    friend T vlen(const Vector3d &a){
        return a.length();
    }

    void in(){
        cin>>x>>y>>z;
    }
    void out(){
        cout<<x<<" "<<y<<" "<<z<<endl;
    }
};//end Vector3d definition
template<class T>
class Line3d{
public :
    Vector3d<T> s, t;
//    static const Vector3d<T> zrop;
    Line3d(){}
    Line3d(const Vector3d<T> &a, const Vector3d<T> &b):s(a), t(b){}


    //判断两线段所在直线平行
    friend bool parallel(const Line3d &line1, const Line3d &line2){
        return sgn(cross(line1.s - line1.t, line2.s - line2.t)) == 0;
    }
 
    //求点到直线的距离
    friend T PointToLine3dVec(const Vector3d<T> &p, const Line3d &line){
        Vector3d<T> vd = line.dirVec();
        return vlen(det(p - line.s, vd)) / vlen(vd);
    }
 
    //直线到直线的距离
    friend T lineToLine(const Line3d &line1, const Line3d &line2){
        if(parallel(line1, line2)){//平行特判
            return PointToLine3dVec(line1.s, line2);
        }
        Vector3d<T> n = det(line1.t - line1.s, line2.t - line2.s);
        Vector3d<T> vd = line2.t - line1.s;
        return fabs(dot(n, vd) / vlen(n));
    }
 
    //方向向量
    Vector3d<T> dirVec()const{
        return t - s;
    }
};

struct Syderline{
    Line3d<double>line;
    double r;
    Syderline(){}
    Syderline(const Vector3d<double> &c, const Vector3d<double> &a, const Vector3d<double> &b){
        r = vlen(a - c);
//        cout<<r<<endl;
        line = Line3d<double>(c, c + det(c- a, c- b));///写成det(a, b);
//        line.s.out();
//        line.t.out();
//        cout<<endl;
    }
    Syderline(const double &ir, const Line3d<double> &iline):r(ir), line(iline){}
    friend bool isInsect(const Syderline &s1, const Syderline &s2, double &dist){
        double len = lineToLine(s1.line, s2.line);
//        cout<<len<<" len (r1 + r2)"<<(s1.r + s2.r)<<endl;
        if( sgn(len - ( s1.r + s2.r) ) <= 0 ){
                return true;
        }else {
            dist = len - (s1.r + s2.r);
        }
        return false;
    }

}sydline[50];
int n;
void solve(){
    bool isLucky = false;
    double minDist = INF, dist;
    FOR(i, n){
        for(int j = i + 1; j < n ;j++){
//            cout<<i<<" "<<j<<endl;
            if(isInsect(sydline[i], sydline[j], dist) ){
                puts("Lucky");
                return ;
            }else {
                minDist = min(minDist, dist);
            }
        }
    }
    printf("%.2f\n", minDist);
}
int main() {
    Vector3d<double>center(0, 0, 0),  a(3, 3, 3), b;
    int T;
    cin>>T;
    while(T--){
        cin>>n;
        FOR(i, n){
            center.in();
            a.in();
            b.in();
            sydline[i]  = Syderline(center, a, b);
        }
        solve();
    }
    return 0;
}




  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值