题意是bob在(0,0)位置要射到(x,y)位置的目标,重力加速度是9.8,告诉你子弹的速度问能不能击中目标,能的话输出最小出射角度,否则输出-1。
子弹到达横坐标为x的时间是t*t = x/v*cos(θ),然后可以求得这个时间下纵坐标到达y=x*tan(θ)-1/2*g*t*t, 右边是关于θ的一个上凸函数,先三分求出最高点,如果最高点比给定的y高那么就有解,只需要在0到三分的结果直接作二分就行,因为另一个解在三分结果到pi/2之间。
否则无解。
#include <bits/stdc++.h>
using namespace std;
#define eps 1e-8
#define pi acos (-1)
#define g 9.8
struct point {
double x, y;
point (double _x = 0, double _y = 0) : x(_x), y(_y) {}
point operator - (point a) const {
return point (x-a.x, y-a.y);
}
point operator + (point a) const {
return point (x+a.x, y+a.y);
}
};
point operator * (point a, double p) {
return point (a.x*p, a.y*p);
}
point a;
double v;
double f (double t) {
return a.x*tan (t) - g*a.x*a.x / (2*v*v*cos (t)*cos (t));
}
void solve () {
double l = 0.0, r = pi/2, ll, rr;
while (r-l > eps) {
ll = (l*2+r)/3.0, rr = (l+2*r)/3.0;
double p1 = f (ll), p2 = f (rr);
if (p1 > p2) {
r = rr;
}
else
l = ll;
}
double ans = (l+r) / 2;
if (f (ans) < a.y) {
printf ("-1\n");
return ;
}
l = 0.0, r = ans;
while (r-l > eps) {
double mid = (l+r)/2;
if (f (mid) > a.y)
r = mid;
else
l = mid;
}
printf ("%.6f\n", (l+r)/2);
return ;
}
int main () {
//freopen ("in", "r", stdin);
int t;
cin >> t;
while (t--) {
cin >> a.x >> a.y >> v;
solve ();
}
return 0;
}