Gym100803 Problem D Space Golf

题目链接

题意:
n≤10个障碍物,一个球从起点弹到终点,距离为d≤10000,反弹次数b≤15,重力g=1,不计中间过程的能量损失(理想模型),求可以越过所有障碍物最小的初速度是多少?
这里写图片描述
做法:
暴力法,对每个弹跳次数搜索所有障碍高,通过p, h, d求初速度。

对于上图中弹跳2次的情况,我们可以看作是3个一模一样的抛物线,因为是理想模型,而又必须从起点跳到终点。这样我们就可以通过取模来直接处理所有的抛物线。

对于弹跳次数b,每个相同抛物线的宽度为d /(b+1),设为x0。那么对于每个障碍将他们的水平距离 p,p%x0即可将他们都移到过原点的抛物线来计算。因为x0不一定是整数,需要自己写一个去模函数。

设p为障碍水平距离,h为障碍高,则由以下两个公式可得:
这里写图片描述

Vy^2 = g*x0*x0*h / 2p(x0 - p) 
Vx^2 = g*g*x0*x0 / 4Vy*Vy

对于每一个弹跳次数b,算出最大的Vy^2+Vx^2作为其V^2,然后在所有的V^2里面找到最小的就是结果。

需要注意的是如果Vy^2小于Vx^2,那么出射角小于45度,这种情况下最小的v是在45度时取到的,即Vx^2=Vy^2=g*x0 / 2。(由公式2可得)

为什么这种情况下最小的v是在45度时取到的?

反省:
1)特判碰到障碍物的情况。
通过样例发现球有可能刚好落在障碍物所在的点。

当时没有考虑到的:
2)x0不一定是整数,需要自己写一个去模函数。

3)如果Vy^2小于Vx^2,那么出射角小于45度,这种情况下最小的v是在45度时取到的。

4)另一种解法:三分 ,可以先看三分入门及练习

代码

#include<iostream>
#include<cmath>
#include<algorithm>
#include<cstdio>
#include<cstring>
using namespace std;

#define EXP 0.00000001
#define INF 1e17

struct
ob {
    double p,h;
};

double  // double取模
mod(double a,double b) {
    if (a<b) return a;
    int t=floor(a/b);
    return (a-b*t);
}

int
main(){
    int n,b,d;
    double ans;
    while(cin>>d>>n>>b) {
        ob c[11];
        for(int i=0;i<n;i++)
            cin>>c[i].p>>c[i].h;
        double maxx,minn=INF,vx2,vy2;
        for(int i=0;i<=b;i++){
            maxx=0;
            double x0=(d*1.0)/(i+1.0);
            bool yep=1;
            for(int j=0;j<n;j++){
                double p=mod(c[j].p,x0);
                double h=c[j].h;
                if (fabs(p-0)<EXP) {yep=0;break;}  // 球落在障碍物处
                maxx=max(maxx,x0*x0*h/(2.0*p*(x0-p)));
            }
            if (!yep) continue;
            vy2=maxx;
            vx2=x0*x0/(4.0*vy2);
            if (vx2>vy2)    vx2=vy2=x0/2.0;  // 45度
            minn=min(vy2+vx2,minn);
        }
        ans=sqrt(minn);
        printf("%.5lf\n",ans);
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值