射箭 为射到靶子的最小出手角度。 出手速度 、靶子的位置 给出。
公式推导。
三角函数 推导 求解。
最终公式
sin(2*p -q ) = (g*a*a + b)/(v*v * sqrt(a*a + b*b))
a , b 为靶子的坐标 v是出手速度。
p 要求的角度
cos q = a/ sqrt(a*a + b*b);
#include <iostream>
#include <cstdio>
#include <cmath>
using namespace std;
const double g = 9.8;
double a,b,v;
void solve(){
double ans = g*a*a/(v*v)+b;
ans/= sqrt(a*a+b*b);
if(ans >=1){
cout << "-1"<<endl;
return;
}
double k = acos(a/sqrt(a*a+b*b));
double s = asin(ans);
s= (s+k)/2;
printf("%.6f\n",s);
}
int main(){
int t ;
cin >>t ;
while(t--){
scanf("%lf%lf%lf",&a,&b,&v);
solve();
}
return 0;
}
也可以三分+ 二分做。
三分精度一直是个问题。 精度卡了一会。
在上凸曲线上找一个 点y 对应的x 。先三分找到 最高点, 再在 0 和最高点之间二分求解。
#include <vector>
#include <list>
#include <map>
#include <set>
#include <deque>
#include <stack>
#include <cstring>
#include <bitset>
#include <algorithm>
#include <functional>
#include <numeric>
#include <utility>
#include <sstream>
#include <iostream>
#include <iomanip>
#include <cstdio>
#include <cmath>
#include <cstdlib>
#include <ctime>
#include <assert.h>
#include <queue>
#define REP(i,n) for(int i=0;i<n;i++)
#define TR(i,x) for(typeof(x.begin()) i=x.begin();i!=x.end();i++)
#define ALLL(x) x.begin(),x.end()
#define SORT(x) sort(ALLL(x))
#define CLEAR(x) memset(x,0,sizeof(x))
#define FILLL(x,c) memset(x,c,sizeof(x))
using namespace std;
const double eps = 1e-9;
#define LL long long
#define pb push_back
const double g = 9.8;
double a,b,v;
double f(double aa){
return a*tan(aa) - g*a*a/(2*v*v*cos(aa)*cos(aa));
}
const double PI = acos(-1.0);
void solve(){
double left = 0;
double right = PI/2;
while(right - left > 1e-9){
double lmid = (left + right)/2;
double rmid = (lmid + right)/2;
if(f(lmid ) < f(rmid)){
left = lmid ;
}else{
right = rmid;
}
}
if( f(left) < b){
cout << "-1"<<endl;
return ;
}
double l = 0;
double r = left;
while(r-l>1e-9){
double mid = (l+r)/2;
if(f(mid)<=b){
l = mid;
}else{
r = mid;
}
}
printf("%.6f\n",l);
}
int main(){
int t ;
cin >>t ;
while(t--){
scanf("%lf%lf%lf",&a,&b,&v);
solve();
}
return 0;
}