sgu-204 Little Jumper

题目大意:

借用一下大神博客的图,http://hi.baidu.com/sabbah/item/67ceef84fa567a1ec2162744

给出b1,t1,b2,t2,l,ds,df,和重力加速的g,左边黑点表示起点,右边黑点表示终点,你可以从起点以任意角度、任意速度投出一个小球,从t1,b1中穿过去,落在l上,然后再重新在落点以任意角度、任意速度投出这个球然后从t2,b2中间穿过去于终点落地,然后求两次投掷速度中的最大值的最小值是多少,也就是MIN(MAX(v1,v2))。




解题思路:

首先我们会发现以在l中间的落脚点为自变量,答案是一个单峰函数,存在最小值,如何证明请自己脑补(其实我不知道)

然后这样我们就可以三分答案去求落脚点了,但是要注意精度,应该这样for(;r-l>=1e-12;)注意精度

然后就是对两次投掷分开求最小速度

对于一次投掷,我们很容易发现45°投出是初速度最小的(其实是生活常识啊),然后由于投掷是一个抛物线,假设以投掷点为原点,然后以落脚点坐标x0,那么45°的解析式就是 y=-1/x0*x(x-x0),然后我们判断以45°投出时是否会触碰到上下界,如果触碰到了,很容易脑补出只需要将角度刚好调整到上下界的高度就行了,具体怎么操作请自己脑补吧(事实上是我讲不清)


AC代码:

#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cmath>
#include <iostream>
#include <algorithm>
#define MAX(a,b) ((a)>(b)?(a):(b))
#define MIN(a,b) ((a)>(b)?(b):(a))

using namespace std;
double b1,t1,b2,t2,l,ds,df,g;

double js(double x,double x_,double b,double t)
{
	double y;
	double a=-1/x;
	double mid=x/2;
	double V=0;
	y=a*x_*x_+x_;
	if(y>=b && y<=t)
	{
		double h=a*mid*mid+mid;
		double t,vx,vy;
		t=sqrt(2*h/g);
		vx=x/t/2;
		vy=g*t;
		V=vx*vx+vy*vy;
	}
	else
	{
		if(y<b)
			a=b/(x_*x_-x*x_);
		else a=t/(x_*x_-x*x_);
		double h=a*mid*(mid-x);
		double t,vx,vy;
		t=sqrt(2*h/g);
		vx=x/t/2;
		vy=g*t;
		V=vx*vx+vy*vy;
	}
	return V;
}

double check(double x)
{
	double x1=ds+x,x2=l-x+df;
	double v1,v2;
	
	v1=js(x1,ds,b1,t1);
	v2=js(x2,l-x,b2,t2);
	
	return MAX(v1,v2);
}

void solve()
{
	double ll=0,rr=l;
	for(;rr-ll>=1e-12;)
	{
		double mid1=(rr-ll)/3+ll,mid2=(rr-ll)/3*2+ll;
		double ans1=check(mid1);
		double ans2=check(mid2);
		if(ans1<ans2) rr=mid2;
		else ll=mid1;
	}
	double ans=check((ll+rr)/2);
	printf("%.6f\n",sqrt(ans));
	return;
}

int main()
{
	for(;scanf("%lf%lf%lf%lf%lf%lf%lf%lf",&b1,&t1,&b2,&t2,&l,&ds,&df,&g)!=EOF;)
		solve();
	return 0;
}


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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值