题意是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; }