HDU 1174 爆头(三维计算几何)

2024-02-19 20:48

本文主要是介绍HDU 1174 爆头(三维计算几何),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

爆头

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)
Total Submission(s): 1340    Accepted Submission(s): 542


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

Author
lwg
这个计算几何题目难度也不是很大
首先要注意一点就是子弹是有方向的,先判断土匪和开枪方向是否一致,这个只要计算一下开枪点和土匪头部圆心的连线,和开枪方向之间的cos值,如果为
正的说明方向一致,如果不是那么方向不一致
其次就是计算出土匪头部圆心,到开枪射线之间的距离,如果比土匪半径小,那么就OK,否则不OK!

#include <iostream>
#include <string.h>
#include <stdio.h>
#include <cmath>
#include <algorithm>
using namespace std;
#define eps 1e-8
#define inf 1e8
#define zero(x) (((x)>0?(x):-(X))<eps)
struct point3
{double x;double y;double z;
}temp,temp1,temp3;
struct line3
{point3 a;point3 b;
};
struct plane3
{point3 a;point3 b;point3 c;double r;
};
point3 xmult(point3 u,point3 v)
{point3 ret;ret.x=u.y*v.z-v.y*u.z;ret.y=u.z*v.x-u.x*v.z;ret.z=u.x*v.y-u.y*v.x;return ret;
}
double dis(point3 a,point3 b)
{return sqrt((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y)+(a.z-b.z)*(a.z-b.z));
}
double vlen(point3 p)
{return sqrt(p.x*p.x+p.y*p.y+p.z*p.z);
}
double dmult(point3 u,point3 v)
{return u.x*v.x+u.y*v.y+u.z*v.z;
}
point3 subt(point3 u,point3 v)
{point3 ret;ret.x=u.x-v.x;ret.y=u.y-v.y;ret.z=u.z-v.z;return ret;
}
double linetoline(line3 u,line3 v)
{point3 n=xmult(subt(u.a,u.b),subt(v.a,v.b));return fabs(dmult(subt(u.a,v.a),n))/vlen(n);
}
double angle_cos(line3 u,line3 v)
{return dmult(subt(u.a,u.b),subt(v.a,v.b))/vlen(subt(u.a,u.b))/vlen(subt(v.a,v.b));
}
double ptoline(point3 p,line3 l)
{return vlen(xmult(subt(p,l.a),subt(l.b,l.a)))/dis(l.a,l.b);
}
int main()
{int t;point3 pos1,pos2,dir,head1,head2,dir1,dir2;double h1,r1,h2,r2,angle,d;line3 a,b;scanf("%d",&t);while(t--){scanf("%lf%lf%lf%lf%lf",&h1,&r1,&pos1.x,&pos1.y,&pos1.z);scanf("%lf%lf%lf%lf%lf%lf%lf%lf",&h2,&r2,&pos2.x,&pos2.y,&pos2.z,&dir.x,&dir.y,&dir.z);head1=pos1;head1.z+=(h1-r1);head2=pos2;head2.z+=(h2*0.9-r2);a.a=head2;//警察-》土匪a.b=head1;b.a=head2;b.b=dir;b.b.x+=b.a.x;b.b.y+=b.a.y;b.b.z+=b.a.z;angle=angle_cos(a,b);if(angle <= -eps){printf("NO\n");continue;}d=ptoline(head1,b);if(d <= r1)printf("YES\n");elseprintf("NO\n");}return 0;
}


这篇关于HDU 1174 爆头(三维计算几何)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/725921

相关文章

hdu1240、hdu1253(三维搜索题)

1、从后往前输入,(x,y,z); 2、从下往上输入,(y , z, x); 3、从左往右输入,(z,x,y); hdu1240代码如下: #include<iostream>#include<algorithm>#include<string>#include<stack>#include<queue>#include<map>#include<stdio.h>#inc

hdu4826(三维DP)

这是一个百度之星的资格赛第四题 题目链接:http://acm.hdu.edu.cn/contests/contest_showproblem.php?pid=1004&cid=500 题意:从左上角的点到右上角的点,每个点只能走一遍,走的方向有三个:向上,向下,向右,求最大值。 咋一看像搜索题,先暴搜,TLE,然后剪枝,还是TLE.然后我就改方法,用DP来做,这题和普通dp相比,多个个向上

usaco 1.3 Mixing Milk (结构体排序 qsort) and hdu 2020(sort)

到了这题学会了结构体排序 于是回去修改了 1.2 milking cows 的算法~ 结构体排序核心: 1.结构体定义 struct Milk{int price;int milks;}milk[5000]; 2.自定义的比较函数,若返回值为正,qsort 函数判定a>b ;为负,a<b;为0,a==b; int milkcmp(const void *va,c

poj 3974 and hdu 3068 最长回文串的O(n)解法(Manacher算法)

求一段字符串中的最长回文串。 因为数据量比较大,用原来的O(n^2)会爆。 小白上的O(n^2)解法代码:TLE啦~ #include<stdio.h>#include<string.h>const int Maxn = 1000000;char s[Maxn];int main(){char e[] = {"END"};while(scanf("%s", s) != EO

hdu 2093 考试排名(sscanf)

模拟题。 直接从教程里拉解析。 因为表格里的数据格式不统一。有时候有"()",有时候又没有。而它也不会给我们提示。 这种情况下,就只能它它们统一看作字符串来处理了。现在就请出我们的主角sscanf()! sscanf 语法: #include int sscanf( const char *buffer, const char *format, ... ); 函数sscanf()和

hdu 2602 and poj 3624(01背包)

01背包的模板题。 hdu2602代码: #include<stdio.h>#include<string.h>const int MaxN = 1001;int max(int a, int b){return a > b ? a : b;}int w[MaxN];int v[MaxN];int dp[MaxN];int main(){int T;int N, V;s

uva 10387 Billiard(简单几何)

题意是一个球从矩形的中点出发,告诉你小球与矩形两条边的碰撞次数与小球回到原点的时间,求小球出发时的角度和小球的速度。 简单的几何问题,小球每与竖边碰撞一次,向右扩展一个相同的矩形;每与横边碰撞一次,向上扩展一个相同的矩形。 可以发现,扩展矩形的路径和在当前矩形中的每一段路径相同,当小球回到出发点时,一条直线的路径刚好经过最后一个扩展矩形的中心点。 最后扩展的路径和横边竖边恰好组成一个直

hdu 1754 I Hate It(线段树,单点更新,区间最值)

题意是求一个线段中的最大数。 线段树的模板题,试用了一下交大的模板。效率有点略低。 代码: #include <stdio.h>#include <string.h>#define TREE_SIZE (1 << (20))//const int TREE_SIZE = 200000 + 10;int max(int a, int b){return a > b ? a :

hdu 1166 敌兵布阵(树状数组 or 线段树)

题意是求一个线段的和,在线段上可以进行加减的修改。 树状数组的模板题。 代码: #include <stdio.h>#include <string.h>const int maxn = 50000 + 1;int c[maxn];int n;int lowbit(int x){return x & -x;}void add(int x, int num){while

hdu 3790 (单源最短路dijkstra)

题意: 每条边都有长度d 和花费p,给你起点s 终点t,要求输出起点到终点的最短距离及其花费,如果最短距离有多条路线,则输出花费最少的。 解析: 考察对dijkstra的理解。 代码: #include <iostream>#include <cstdio>#include <cstdlib>#include <algorithm>#include <cstrin