题目大意:
一个球想从0弹到d,中间有n个木板在Pos i,高度为Height i ,问在至多落下Bn次的情况下(不包括首尾),最小初始速度是多少。
思路:
可以发现,当小球在地上弹跳的次数x确定时,vx和vy的关系是可以知道的,然后将√(vx^2+vy^2)化简以后可以得到只由vy表示的一个函数,发现是先递减后递增,符合三分条件,所以我们考虑三分vy。对于在地上弹跳次数的限制可以通过枚举的方式,再进行三分,最后得到最小的那个答案即可。因为三分过程中,可能vy在某一个值的时候并不能保证每个障碍物都能跳过去。但是我们可以发现,在三分过程中,如果vy=mid时候不能保证跳过去,那么vy肯定要增大。这样也就可以避免刚开始对vy范围的确定。
代码:
#include<stdio.h>
#include<string.h>
#include<math.h>
#include<algorithm>
#define eps 0.00000000001
using namespace std;
double min(double a,double b)
{
return a<b?a:b;
}
double vx,vy,d,db;
int n,b;
struct node{
double p,h;
}q[15];
double cal(double y,int x)
{
double t,sum;
int l,ok=1;
vx=d/(2*(x+1)*y);
for(int i=1;i<=n;i++)
{
t=q[i].p/vx;
l=1;
while(q[i].p>=l*db)
{
l++;
}
l--;
t=t-l*(db/vx);
double yy=y*t-0.5*t*t;
if(yy>=q[i].h){
ok=1;
}
else {
ok=0;break;
}
}
sum=sqrt(y*y+vx*vx);
if(ok==0)return -1;
return sum;
}
double solve(double l,double r,int p)
{
double mid,midmid,mid_val,midmid_val;
while(fabs(l-r)>eps)
{
mid=(l+r)/2.0;
midmid=(mid+r)/2.0;
mid_val=cal(mid,p);
midmid_val=cal(midmid,p);
if(mid_val<=midmid_val&&mid_val!=-1)r=midmid;
else l=mid;
}
mid=(l+r)/2.0;
return mid;
}
bool cmp(node a,node b)
{
return a.p<b.p;
}
int main()
{
int i,j,k;
double mini=10000001;
while(scanf("%lf%d%d",&d,&n,&b)!=EOF)
{
mini=10000001;
for(i=1;i<=n;i++)
scanf("%lf%lf",&q[i].p,&q[i].h);
sort(q+1,q+1+n,cmp);
for(i=0;i<=b;i++)
{
db=d/(i+1);
vy=solve(0,10000000,i);
vx=d/(2*(i+1)*vy);
double ans=sqrt(vy*vy+vx*vx);
mini=min(mini,ans);
}
printf("%.5f\n",mini);
}
}