爆头

Problem Description
gameboy是一个CS高手,他最喜欢的就是扮演警察,手持M4爆土匪的头。也许这里有人没玩过CS,有必要介绍一下“爆头”这个术语:所谓爆头,就是子弹直接命中对方的头部,以秒杀敌人。
现在用一个三维的直角坐标系来描述游戏中的三维空间(水平面为xoy平面,z轴正方向是上方)。假设游戏中角色的头是一个标准的球。告诉你土匪的身高,头部半径,所站位置的坐标;gameboy所控警察的身高,头部半径,所站位置的坐标,以及枪头所指方向的单位向量。gameboy所控警察所握的是M4,抢瞄准时枪膛中的子弹跟视线基本同线,我们忽略它们的距离,就当成同线。由于土匪手持AK47,所以他是很嚣张地正立着。而警察手持M4,正在瞄准,由于瞄准时身体微弯,视线从头心出发,他头部的实际高度比正立时低10%。
你的任务就是,计算gameboy在这一刻扣下扳机,能否爆土匪的头。注意:这里忽略子弹的直径和重力作用,也就是说子弹是无限小的,弹道是一条笔直的射线,警察与土匪间没有障碍物。并且只要子弹擦到头部,哪怕是边缘,也算爆头。
 
Input
测试数据的第一行有一个正整数T,表示有T组测试数据。每组数据的第一行有五个实数,h1,r1,x1,y1,z1,分别表示土匪的身高,头部半径以及所站的位置。第二行有八个实数,h2,r2,x2,y2,z2,x3,y3,z3,分别表示警察的身高,头部半径,所站位置,以及枪头所指方向的方向向量。
 
Output
每一组输入数据对应一行输出。如果能爆土匪的头,输出"YES",否则输出"NO"。
 
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
YES YES
解题思路:问题可转换为空间中点到直线的距离。可利用向量的点积运算求出夹角
#include<iostream>
#include<math.h>
using namespace std;
struct lmx{
        double x;
  double y;
  double z;
};
double cnt(lmx s1,lmx s2)
{
 return (s1.x*s2.x+s1.y*s2.y+s1.z*s2.z);
}
double fan(lmx s1,lmx s2)
{
 return sqrt(s1.x*s1.x+s1.y*s1.y+s1.z*s1.z)*sqrt(s2.x*s2.x+s2.y*s2.y+s2.z*s2.z);
}
lmx s1,s2;
int main()
{
   int n;
   cin>>n;
   double hight1,radius1,x1,y1,z1;
   double hight2,radius2,x2,y2,z2,dir1,dir2,dir3;
   while(n--)
   {
        cin>>hight1>>radius1>>x1>>y1>>z1;
        cin>>hight2>>radius2>>x2>>y2>>z2>>dir1>>dir2>>dir3;
  s1.x=x1-x2;
  s1.y=y1-y2;
  s1.z=z1+hight1-radius1-(z2+hight2*0.9-radius2);
  s2.x=dir1;
  s2.y=dir2;
  s2.z=dir3;
        double s=sqrt(s1.x*s1.x+s1.y*s1.y+s1.z*s1.z);
  double mm=s*sin(acos(cnt(s1,s2)/fan(s1,s2)));
  if(mm<=radius1) cout<<"YES"<<endl;
  else cout<<"NO"<<endl;
   }
 return 0;
}
posted @ 2013-03-19 21:31  forevermemory  阅读(214)  评论(0编辑  收藏  举报