HDU 2298 (三分)

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


你可能感兴趣的:(HDU 2298 (三分))