2014-2015 ACM-ICPC, Asia Tokyo Regional Contest D题 Space Golf(三分)

来源:互联网 发布:电脑管家数据恢复 编辑:程序博客网 时间:2024/05/22 16:44

题目大意:

一个球想从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.00000000001using 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);    }}


0 0