tmk射气球

问题 : tmk射气球

题目描述

有一天TMK在做一个飞艇环游世界,突然他发现有一个气球沿匀速沿直线飘过,tmk想起了他飞艇上有一把弓,他打算拿弓去射气球,为了提高射击的准确性,他首先在飞艇上找到一个离气球最近的一个点,然后射击(即使气球在飞船的正上方),现在求某些时刻飞艇上的点和气球的距离最小是多少(这个最小距离我们简称为飞艇到气球的距离)。

输入

第一行一个整数T(T<=20),表示有T组测试数据

每组测试数据,有两行。

第一行有5个整数,h,x1,y1,x2,y2,其中h表示飞船的高度,飞船可抽象为一个线段,(x1,y1)(x2,y2)分别是这个线段的端点(有可能会有(x1,y1)(x2,y2)重合的情况)

第二行有6个整数,x,y,z,X,Y,Z分别表示气球的在第0秒的时候的横坐标,纵坐标,高度,一秒时间气球横坐标的变化量,一秒时间气球纵坐标的变化量,一秒时间气球高度的变化量(如果现在气球在(x0,y0,z0)下一秒坐标就为(x0+X,y0+Y,z0+Z))

第三行1个整数n,表示询问组数

接下来的n行,每行一个整数,表示询问的秒数t

题目涉及的整数除了T以外,范围均为[0,1000]

输出

每组询问输出n行,每行输出一个数,表示在t秒的时候飞艇与气球的距离最小是多少,保留两位小数

样例输入

1
1 1 1 2 2
0 0 0 4 4 4
2
0
3

样例输出

1.73
17.92

题意解析

题目意思就是求空间内一个定点到一个线段的最短距离。

程序代码

#include <cstdio>
#include <cmath>
#include <cstring>
#define min(a,b) a<b?a:b
#define dd double
#define ll long long

dd dis(ll x1,ll y1,ll x2,ll y2){			//求两点距离 
	double d=(x1-x2)*(x1-x2)+(y1-y2)*(y1-y2);
	return sqrt(d);
}
int rui(dd a,dd b,dd c){					//求三角形内一个角是否为锐角 
	if(a*a+b*b>=c*c)
		return 1;
	return 0;
}

int main()
{
	int n,t,t0;
	ll x1,x2,y1,y2,h;
	ll x,y,z,X,Y,Z,h0,x3,y3,z3;
	dd a,b,c,b0,c0,l,f,s;
	scanf("%d",&t0);
	while(t0--){
		scanf("%lld%lld%lld%lld%lld",&h,&x1,&y1,&x2,&y2);
		scanf("%lld%lld%lld%lld%lld%lld",&x,&y,&z,&X,&Y,&Z);
		scanf("%d",&n);
		while(n--){
			scanf("%d",&t);
			x3=x+t*X; y3=y+t*Y; z3=z+t*Z;
			h0=fabs(h-z3);
			if(x1==x2&&y1==y2){			//飞船两点重合的时候 
				f=dis(x1,y1,x3,y3);
				s=sqrt(f*f+h0*h0);
				printf("%.2lf\n",s);
				continue;
			}
			a=dis(x1,y1,x2,y2);
			b0=dis(x1,y1,x3,y3);
			c0=dis(x2,y2,x3,y3);
			b=sqrt(b0*b0+h0*h0);
			c=sqrt(c0*c0+h0*h0);
			if(a==b+c){					//气球在飞船上以及在飞船延长线上 
				l=0.00;
				printf("%.2lf\n",l);
				continue;
			}
			if(a+b==c){
				l=b;
				printf("%.2lf\n",l);
				continue;
			}
			if(a+c==b){
				l=c;
				printf("%.2lf\n",l);
				continue;
			}
			int flag=rui(a,b,c)+rui(a,c,b);		//如果以飞船为边的
			两个夹角都是锐角,那最短距离就是三角形的高h 
			if(flag==2){
				f=(a+b+c)/2;
				s=sqrt(f*(f-a)*(f-b)*(f-c));
				l=s*2/a;
				printf("%.2lf\n",l);
				continue;
			}
			else{						//存在一个钝角的话,
			最短距离就是到端点的最小值 
				l=min(b,c);
				printf("%.2lf\n",l);
				continue;
			}
		}
	}
	return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值