叉积求距离(简单几何)

82 篇文章 0 订阅
31 篇文章 0 订阅

description

实验室胡某是LOL一区最强王者,其上分神器就是ADCarry中的皮城女警。话说这女警不但长的好看,手还是全联盟最长的。

女警的R技能完美一击呢,其实就是点爆对方的头,简称爆头。所谓爆头,就是子弹直接命中对方的头部,以秒杀敌人。

现在用一个三维的直角坐标系来描述游戏中的三维空间(水平面为xoy平面,z轴正方向是上方)。

假设游戏中角色的头是一个标准的球。告诉你对面暴走金克斯的身高,头部半径,所站位置的坐标;

胡某所控女警的身高,头部半径,所站位置的坐标,以及枪头所指方向的单位向量。

女警的枪瞄准时枪膛中的子弹跟视线基本同线,我们忽略它们的距离,就当成同线。

金克斯呢,很是嚣张地正立着。现在女警正在瞄准,由于瞄准时身体微弯,视线从头心出发,他头部的实际高度比正立时低10%。

你的任务就是,计算女警在这一刻扣下扳机,能否爆金克斯的头。

注意:这里忽略子弹的直径和重力作用,也就是说子弹是无限小的,弹道是一条笔直的射线,两人之间没有障碍物。

并且只要子弹擦到头部,哪怕是边缘,也算爆头。

input

测试数据的第一行有一个正整数T,表示有T组测试数据。

每组数据的第一行有五个实数,h1,r1,x1,y1,z1,分别表示金克斯的身高,头部半径以及所站的位置。

第二行有八个实数,h2,r2,x2,y2,z2,x3,y3,z3,分别表示女警的身高,头部半径,所站位置,以及枪头所指方向的方向向量。

output

每一组输入数据对应一行输出。如果能爆金克斯的头,输出Boom;,否则输出Pity。

sample_input

2
1.62 0.1 10.0 10.0 10.0
1.80 0.09 0.0 0.0 0.0 1.0 1.0 1.0
1.62 0.1 0.0 0.0 0.0
1.80 0.09 10.0 10.0 10.0 -1.0 -1.0 -1.0

sample_output

Boom
Boom




此题若仅仅认为是求一个叉积判断距离那就大错特错了,刚开始是说怎么老是wa,后来看网上别人帖子才受到启发原来刚开始第一步就少了判断射击方向,所以如果射击是反的叉积判断距离和射正的判断的距离一样,所以第一步判断方向一定不能少,一个向量点乘就搞定,至于后来的叉积判断距离,我是将三维分解为x,y;x,z;y,z这三个垂直方向来三次判断的二维叉积,至于三维叉积的判断方法由于本人能力有限还不足以完成,下面附上代码仅供参考:




#include <iostream>
#include<stdio.h>
#include<cmath>
using namespace std;
double ss(double ax,double ay,double bx,double by,double cx,double cy)//此函数算叉积,尽管是二维叉积......
{
    return abs((bx-ax)*(cy-ay)-(by-ay)*(cx-ax))/sqrt((ax-cx)*(ax-cx)+(ay-cy)*(ay-cy));
}
double jiao(double x1,double y1,double z1,double x2,double y2,double z2)//此函数判断射击方向,用的是向量点乘的逆运算,算出cos值
{
    return (x1*x2+y1*y2+z1*z2)/(sqrt(x1*x1+y1*y1+z1*z1)*sqrt(x2*x2+y2*y2+z2*z2));
}
int main()
{
    int n;
    double h1,r1,x1,y1,z1,h2,r2,x2,y2,z2,x3,y3,z3;
       scanf("%d",&n);
        for(int i=0;i<n;i++)
        {
            scanf("%lf%lf%lf%lf%lf",&h1,&r1,&x1,&y1,&z1);
        scanf("%lf%lf%lf%lf%lf%lf%lf%lf",&h2,&r2,&x2,&y2,&z2,&x3,&y3,&z3);
        double X1=x2,Y1=y2,Z1=z2+h2*0.9-r2,X2=X1+x3,Y2=Y1+y3,Z2=Z1+z3,X3=x1,Y3=y1,Z3=z1+h1-r1;
        if(jiao(x3,y3,z3,X3-X1,Y3-Y1,Z3-Z1)<=0)
        {
            cout<<"Pity"<<endl;
            continue;
        }
        else
        {
        if(ss(X1,Y1,X3,Y3,X2,Y2)-r1<=1e-6&&ss(X1,Z1,X3,Z3,X2,Z2)-r1<=1e-6&&ss(Y1,Z1,Y3,Z3,Y2,Z2)-r1<=1e-6)
            cout<<"Boom"<<endl;
        else cout<<"Pity"<<endl;}
        }
    return 0;
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值