小周的曲射炮

题目链接: 小周的曲射炮
题目来源: 牛客网

题目描述

小周最近在玩一款二战游戏,他因而对曲射炮的轨迹产生了很大的兴趣,但是在尝试计算后,小周发现这个问题并不是那么简单,他因而来请教你这位计算机高手,请你来帮帮他吧。问题大致可描述为,在二维平面的原点(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=Vxt y = V y ∗ t − 0.5 g t ² y = Vy*t - 0.5gt² y=Vyt0.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²+yC=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了

C/C++中的atan和atan2函数详解…

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值