HDU - 4617 Weapon(基础三维几何 直线之间的距离)

题目链接:click.

题意: 给你n个圆,每个圆包括的信息:圆心,圆上的两点,确保三点不成一线.以该圆向两端发射出的射线形成圆柱.
求 若其中有圆柱相交,输出"Lucky"
否则输出最近两个圆柱的距离

解法:
题目已给圆心o,圆上的两点a,b
可以通过向量oa与向量ob的叉积计算出垂直圆面的向量v,
通过o+v得到o’,这样就得到该圆柱体中心轴oo’
枚举每两个圆柱体的中心轴,
计算之间的距离d即可
当d<=line[i].r+line[j].r时即为相交,输出"Lucky"
否则更新最小值ans=min(ans,d-(line[i].r+line[j].r))

代码:

#include<cmath>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int MAXN=1e3+5;
const double EPS=1e-6;
const double PI=acos(-1);
inline int sgn(double a){ return a < -EPS ? -1 : a > EPS; }
inline int cmp(double a, double b){ return sgn(a-b); }
int n,m,T;
struct Point3;
struct Line3;
typedef Point3 Vector3;
struct Point3{
    double x,y,z;
    Point3(){}
    Point3(double a, double b, double c):x(a),y(b),z(c){}
    double disToPoint(Point3 p){return sqrt((x-p.x)*(x-p.x)+(y-p.y)*(y-p.y)+(z-p.z)*(z-p.z));}
    double len(){return sqrt(x*x+y*y+z*z);}
    void read(){scanf("%lf%lf%lf",&x,&y,&z);}
    Point3 operator+(Vector3 v){return {x+v.x,y+v.y,z+v.z};}
    Vector3 operator-(Point3 p){return {x-p.x,y-p.y,z-p.z};}
    Vector3 operator^(Vector3 v){return {y*v.z-z*v.y,z*v.x-x*v.z,x*v.y-y*v.x};}//叉乘
    double operator*(Vector3 v){return x*v.x+y*v.y+z*v.z;}//点乘
    Vector3 operator*(double d){return {x*d,y*d,z*d};}
    Vector3 operator/(double d){return {x/d,y/d,z/d};}
    bool operator==(Point3 p){return cmp(x,p.x)==0&&cmp(y,p.y)==0&&cmp(z,p.z)==0;}
    bool operator<(Point3 p){if(cmp(x,p.x)==0&&cmp(y,p.y))return z<p.z;else if(cmp(x,p.x))return y<p.y;return x<p.x;}
};

struct Line3{
    Line3(){}
    Line3(Point3 a,Point3 b,double c=0){s=a,e=b;r=c;}
    double disToLine(Line3 v){
        Point3 n=((s-e)^(v.s-v.e));
        return fabs(((s-v.s)*n))/n.len();
    }
    Point3 s,e;
    double r;
};

Line3 l[55];
void solve(){
    double ans=1e9;
    for(int i=1;i<=n;i++){
        for(int j=i+1;j<=n;j++){
            double dis=l[i].disToLine(l[j]);
            if(cmp(dis,l[i].r+l[j].r)<=0){
                printf("Lucky\n");
                return;
            }
            ans=min(ans,dis-l[i].r-l[j].r);
        }
    }
    printf("%.2lf\n",ans);
}
void init(){
    scanf("%d",&n);
    Point3 p1,p2,p3;
    for(int i=1;i<=n;i++){
        p1.read();
        p2.read();
        p3.read();
        l[i]={p1,p1+((p2-p1)^(p3-p1)),p1.disToPoint(p2)};
    }
}
int main(){
    scanf("%d",&T);
    while(T--){
        init();
        solve();
    }
    return 0;
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值