HDU - 1174:爆头 (三维平面点到射线的距离)

时间:2022-09-11 13:33:34

pro:给定警察的射击位置,设计方向,敌人的位置,敌人的头部半径,问子弹是否可以射到头部。

sol:即问头部中点到子弹射线的距离是否小于等于头部半径。

和二维的点到直线一样的操作。 det/dot; 用平行四边形面积/底。 那么唯一的问题就是三维向量的det怎么求。 如图:

HDU - 1174:爆头 (三维平面点到射线的距离)

 

由于是射线,还要判定是否同向。

#include<bits/stdc++.h>
#define rep(i,a,b) for(int i=a;i<=b;i++)
using namespace std;
const int maxn=200010;
struct point3
{
    double x,y,z;
    point3(){}
    point3(double xx,double yy,double zz):x(xx),y(yy),z(zz){}
};
point3 operator -(point3 a,point3 b){ return point3(a.x-b.x,a.y-b.y,a.z-b.z);}
point3 A,B,C;
double det(point3 a,point3 b){
    double x=a.x*b.y-a.y*b.x;
    double y=a.x*b.z-a.z*b.x;
    double z=a.y*b.z-a.z*b.y;
    return sqrt(x*x+y*y+z*z);
}
double dot(point3 a,point3 b){
    return a.x*b.x+a.y*b.y+a.z*b.z;
}
int main()
{
    int T; double H1,H2,R1,R2;
    scanf("%d",&T);
    while(T--){
        scanf("%lf%lf%lf%lf%lf",&H1,&R1,&A.x,&A.y,&A.z);
        scanf("%lf%lf%lf%lf%lf",&H2,&R2,&B.x,&B.y,&B.z);
        scanf("%lf%lf%lf",&C.x,&C.y,&C.z);
        A.z+=H1-R1; B.z+=H2*0.9-R2;
        double ans=det(A-B,C)/sqrt(dot(C,C));
        if(dot(A-B,C)>=0&&ans<=R1) puts("YES");
        else puts("NO");
    }
    return 0;
}