• 博客园logo
  • 会员
  • 众包
  • 新闻
  • 博问
  • 闪存
  • 赞助商
  • HarmonyOS
  • Chat2DB
    • 搜索
      所有博客
    • 搜索
      当前博客
  • 写随笔 我的博客 短消息 简洁模式
    用户头像
    我的博客 我的园子 账号设置 会员中心 简洁模式 ... 退出登录
    注册 登录
L&King
有何不可!
   首页    新随笔    联系   管理    订阅  订阅

HDU 2298 Toxophily 【二分+三分】

一个人站在(0,0)处射箭,箭的速度为v,问是否能够射到(x,y)处,并求最小角度。

首先需要判断在满足X=x的情况下最大高度hmax是否能够达到y,根据物理公式可得

h=vy*t-0.5*g*t*t

vx=v*cos(a)

vy=v*sin(a)

t=x/vx

由此可推出:h=x*tan(a)-(g*x*x)/(2*v*v)/cos(a)/cos(a)

g,x,v已知,设A=x,B=(g*x*x)/(2*v*v)

原式化为:h=A*tan(a)+(-B/(cos(a)^2))

由于凸函数有以下性质:

1,如果f和g是凸函数,那么m(x) = max{f(x),g(x)}和h(x) = f(x) + g(x)也是凸函数。

2,如果f和g是凸函数,且g递增,那么h(x) = g(f(x))是凸函数。

tan(a)为凸函数,cos(a)为凸函数,-(1/x)为增凸函数。所以h为凸函数。

以上是h函数是凸函数的证明,因为网上的题解基本都是一句带过,小白的我又看不懂,只能自己证明。若有出错的地方,请大神指出。拜谢。

因此可以三分出hmax。

若能到达,再通过二分得到最小的仰角。

#include<stdio.h>
#include<string.h>
#include<math.h>
const double pi=acos(-1.0),g=9.8,eps=1e-8;
double x,y,v;
double cal(double a){
    double vx=v*cos(a);
    double vy=v*sin(a);
    double t=x/vx;
    double h=vy*t-g*t*t/2;
    return h;
}
double thrdiv(){
    double l=0.0,r=pi/2.0,lm,rm;
    while(r-l>eps){
        lm=(l*2.0+r)/3.0;
        rm=(l+r*2.0)/3.0;
        if(cal(lm)>cal(rm))
            r=rm;
        else
            l=lm;
    }
    return l;
}
double bin(double a){
    double l=0,r=a,mid;
    while(r-l>eps){
        mid=(l+r)/2;
        if(cal(mid)<y)
            l=mid;
        else
            r=mid;
    }
    return l;
}
int main(){
    double ans,h;
    int t;
    scanf("%d",&t);
    while(t--){
        scanf("%lf%lf%lf",&x,&y,&v);
        ans=thrdiv();h=cal(ans);
        if(y-h>eps)
            printf("-1\n");
        else if(fabs(y-h)<=eps)
            printf("%.6f\n",ans);
        else{
            ans=bin(ans);
            printf("%.6f\n",ans);
        }
    }
    return 0;
}

 

posted @ 2016-07-26 19:25  L&King  阅读(387)  评论(0)    收藏  举报
刷新页面返回顶部
博客园  ©  2004-2025
浙公网安备 33010602011771号 浙ICP备2021040463号-3