题目链接: 小周的曲射炮
题目来源: 牛客网
文章目录
题目描述
小周最近在玩一款二战游戏,他因而对曲射炮的轨迹产生了很大的兴趣,但是在尝试计算后,小周发现这个问题并不是那么简单,他因而来请教你这位计算机高手,请你来帮帮他吧。问题大致可描述为,在二维平面的原点(0,0)处有一曲射炮,炮口可沿任意方向发出初速度为v的炮弹,小周想要把炮弹投射到点(x,y)处,现在你需要帮助小周得出炮口与地面夹角的弧度。为使问题简化,我们忽略空气阻力,x轴沿水平方向分布。设重力加速度g=9.8。
输入
第一行为一个整数T,表示输入的数据组数。
每组数据对应一行输入, 依次为三个正整数x,y,v,含义如题面所示。
输出
每组数据输出一行,如果无论如何挑战炮口与地面夹角都无法将炮弹投射这目标处,输出“NO SOLUTION.”(不包括引号),否则从小到大输出所有可能的弧度(均四舍五入至小数点后5位,如果有两个解四舍五入至小数点后5位后相同,只视为一个解),中间用一个空格分隔。
备注
1 ≤ T ≤ 200
0 < x ≤ 10000
0 < y ≤ 10000
0 < v ≤ 20000
样例输入
4
45 56 78
32 78 55
33 33 25
12 25 25
样例输出
0.93196 1.53271
1.24254 1.50973
NO SOLUTION.
1.25456 1.43951
题目解读:
已知任意方向的初速度v, 水平位移x, 竖直位移y,求斜抛夹角θ: V y = v s i n θ Vy = vsinθ Vy=vsinθ x = V x ∗ t x = Vx * t x=Vx∗t y = V y ∗ t − 0.5 g t ² y = Vy*t - 0.5gt² y=Vy∗t−0.5gt²得一元二次方程: ( g x ² / 2 v ² ) t a n θ ² − x t a n θ + g x ² / 2 v ² + y = 0 ( 一 般 式 ) (gx²/2v²)tanθ² - xtanθ + gx²/2v²+y=0 (一般式) (gx²/2v²)tanθ²−xtanθ+gx²/2v²+y=0(一般式) A = g x ² / 2 v ² A = gx²/2v² A=gx²/2v² B = − x B = -x B=−x C = g x ² / 2 v ² + y , 即 C = A + y C = gx²/2v²+y , 即 C = A + y C=gx²/2v²+y,即C=A+y Δ = B ² − 4 A C Δ = B² - 4A C Δ=B²−4AC(1)如果Δ < 0,无解,即不存在弧度,输出“NO SOLUTION.” 。
(2)如果Δ ≥ 0,tanθ = [ -B ± (B²−4AC^(1/2) ] / (2A)。
参考代码:
#include <iostream>
#include <algorithm>
#include <cmath>
#include <cstdio>
using namespace std;
double g = 9.8;
int main()
{
int t;
cin >> t;
while(t--) {
int x, y, v;
cin >> x >> y >> v;
// 一元二次方程 一般式 Atanθ² - Btanθ + C=0
double A = (g*x*x)/(2*v*v);
double B = -x;
double C = A + y;
double data = B*B - 4*A*C;
if(data < 0) {
// 点(x, y)在抛物线上方,无解
cout << "NO SOLUTION." << endl;
continue;
}
// 根据一元二次方程公式法求出两个tanθ的值
double tan1 = (-B+sqrt(data)) / (2*A);
double tan2 = (-B-sqrt(data)) / (2*A);
// 利用#include <cmath> 头文件下的 atan()函数求θ的弧度,
// atan()接受的是一个正切值(tanθ)得到夹角,
// atan()的值域是从-90~90 只返回一个角度。
double ans1 = atan(tan2);
double ans2 = atan(tan1);
// 从小到大输出所有可能的弧度
if(fabs(ans1 - ans2) > 1e-6) {
printf("%.5lf %.5lf\n",ans1, ans2);
}
else {
// 两个解四舍五入至小数点后5位后相同,视为一个解
printf("%.5lf\n",ans1);
}
}
return 0;
}
已知tanθ求其弧度:
在C语言的math.h或C++中的cmath中有两个求反正切的函数atan(double x)与atan2(double y,double x) 他们返回的值是弧度 要转化为角度再自己处理下。
前者接受的是一个正切值(直线的斜率)得到夹角,但是由于正切的规律性本可以有两个角度的但它却只返回一个,因为atan的值域是从-90~90 也就是它只处理一四象限,所以一般不用它。
第二个atan2(double y,double x) 其中y代表已知点的Y坐标 同理x ,返回值是此点与远点连线与x轴正方向的夹角,这样它就可以处理四个象限的任意情况了,它的值域相应的也就是-180~180了