二分法作为分治中最常见的方法,适用于单调函数,逼近求解某点的值。但当函数是凸性函数时,二分法就无法适用,这时三分法就可以“大显身手”~~

如图,类似二分的定义Left和Right,mid = (Left + Right) / 2,midmid = (mid + Right) / 2; 如果mid靠近极值点,则Right = midmid;否则(即midmid靠近极值点),则Left = mid;
#include<iostream>
#include<cmath>
#define PI (acos(-1))
#define eps 1e-9
using namespace std;
/*三分法求凸函数极值,二分法求根*/
/*根据物理知识有,y=x*tan(a) - 0.5 * g * x * x * 1 / (v*v*cos(a)*cos(a)) */
double gety(double x,double a,double v){
return x*tan(a) - 0.5 * 9.8 * x * x / (v*v*cos(a)*cos(a));
}
double divide3(double left,double right,double x,double v){
double mid,mmid;
while(right-left>eps){
mid=(left+right)/2;
mmid=(mid+right)/2;
double _y=gety(x,mid,v);
double __y=gety(x,mmid,v);
if( _y>__y)
right=mmid;
else
left=mid;
}
return (mid+mmid)/2;
}
double divide2(double left,double right,double x,double v,double y){
double mid;
while(right-left>eps){
mid=(right+left)/2;
double _y=gety(x,mid,v);
if(y>_y)
left=mid;
else
right=mid;
}
return mid;
}
int main(){
int coun;
cin>>coun;
double x,y,v;
while(coun--){
cin>>x>>y>>v;
double a=divide3(0,PI/2,x,v);
double _y=gety(x,a,v);
if( _y < y)
cout<<-1<<endl;
else{
a=divide2(0,a,x,v,y);
printf("%.6lf\n",a);
}
}
return 0;
}