hdu 2298 Toxophily 公式 或者 三分+二分。

射箭 为射到靶子的最小出手角度。 出手速度  、靶子的位置 给出。

公式推导。

三角函数 推导 求解。


最终公式

  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;
}




  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值