1 条题解

  • 0
    @ 2025-8-24 22:30:05

    自动搬运

    查看原文

    来自洛谷,原作者为

    avatar DeaphetS
    什么时候才能回归绿名啊

    搬运于2025-08-24 22:30:05,当前版本为作者最后更新于2022-07-20 18:36:12,作者可能在搬运后再次修改,您可在原文处查看最新版

    自动搬运只会搬运当前题目点赞数最高的题解,您可前往洛谷题解查看更多

    以下是正文


    吃了语文不好的亏啊...

    首先令 Tf=0T_f=0,让 TdT_d 平移到原先 TdTfT_d-T_f 的时刻,这样可以方便我们后续的计算。接着考虑二分,因为我们懒得去想狗具体怎么蛇皮走位,所以为了省事可以二分答案来判断狗是否能够在指定位置接到盘子。假设狗接到盘子时的位置是 (x,y)(x,y),那么根据平抛运动的公式可以得出:

    $$\begin{cases} V_f\cdot t=x\\ \frac{1}{2}a_ft^2=H_f-y\\ a_f=1\\ \end{cases} $$

    也就是说如果我们二分了狗接盘子的横坐标 xx,就可以很快计算出对应的纵坐标 yy 以及时间 tt,接着就只需要考虑如何判断狗是否能按时到达指定地点了。注意这里 Clarifications\texttt{Clarifications} 说的是,狗的跳跃过程是瞬间获得能够跳到 HdH_d 高度的垂直速度,其实这还是有一点歧义的。真正的题意是:狗的跳跃过程是瞬间获得能够在未来某一时刻恰好到达 HdH_d 高度的速度(即到达 HdH_d 这个高度时正好垂直速度为 00)。也就是说不存在先到达 (x,0)(x,0),再原地起跳直接到达 HdH_d 并在途中顺便接到处于 (x,y)(x,y) 的盘子这种情况的,也并不是说狗提前在某一时刻原地起飞到 HdH_d 之后再自由落体的,而是在竖直方向产生一个最高点为 HdH_d 的竖直上抛运动,本人就因为这个 WA\texttt{WA} 了好几发。

    既然不能直接原地起跳接住盘子,那这也就意味着小狗需要先提前在某个位置跳起,再依靠重力让其水平方向到达 xx 时恰好到达 (x,y)(x,y)。不过这里我们不能借助公式来计算小狗起跳时的位置,而是要考虑小狗在垂直方向的位移来计算跳跃所花费的时间,因为小狗在水平方向上移动的速度是不确定的。那么设小狗起跳后到达 yy 这一高度所花的时间为 tjt_j,起跳时瞬间获得的竖直方向的速度为 v0v_0,就有方程:

    $$\begin{cases} v_0t_j-\frac{1}{2}a_dt_j^2=y\\ a_d=3\\ \end{cases} $$

    在解这个方程前我们还需要先算出 v0v_0 的值,那么借助物理学中关于竖直上抛运动的一个公式 H=v022gH=\frac{v_0^2}{2g}(可用动能定理证明)就能得出 v0=6Hdv_0=\sqrt{6H_d}。带回到原式中解一个一元二次方程就能得到 tj=6Hd±6Hd6y3t_j=\frac{\sqrt{6H_d}\pm \sqrt{6H_d-6y}}{3},显然我们是要取更小的解。于是结合小狗要出发后才能起跳这一信息,我们得知了小狗能够到达 (x,y)(x,y) 的一个必要条件,那就是:

    tTd6Hd6Hd6y3t-T_d\ge \frac{\sqrt{6H_d}- \sqrt{6H_d-6y}}{3}

    除了这一条件外,我们还需要保证 yHdy\le H_d 以及 Vd(tTd)xV_d\cdot (t-T_d)\ge x ,这样就能完成对小狗能否到达 (x,y)(x,y) 的判断,这时对应的答案就是 t+xVdt+\frac{x}{V_d}

    当然不要忘了 Clarifications\texttt{Clarifications} 中的另外一条:当飞盘落在地面上时瞬间停止运动。所以我们需要注意二分的区间,即飞盘落地时所处的位置 xRx_R。同样可以列出方程 $\begin{cases} V_f\cdot t=x_R\\ \frac{1}{2}a_ft^2=H_f\\ a_f=1\\ \end{cases} $ ,算出 xR=Vf2Hfx_R=V_f\sqrt {2H_f} 就能够确定二分的右端点。最后再处理一下狗无法在空中接到盘子的情况,这一情况的答案为 $\max(\frac{x_R}{V_f},T_d+\frac{x_R}{V_d})+\frac{x_R}{V_d}$,取 max\max 的部分是为了比较狗到达指定地点的时间和飞盘实际落地的时间,这样就大功告成了。

    注意 eps\texttt{eps} 不要开太小,否则会因为精度问题而导致死循环。

    #include<bits/stdc++.h>
    using namespace std;
    #define ld double
    const ld eps=1e-6;
    ld tf,vf,hf,td,vd,hd,l,r,x,ans;
    int main()
    {
    	cin>>tf>>vf>>hf>>td>>vd>>hd;
    	td-=tf;
    	r=vf*sqrt(2*hf);
    	ans=max(r/vf,td+r/vd)+r/vd;
    	while(l+eps<r){
    		x=(l+r)*0.5;
    		ld t=x/vf;
    		ld y=hf-0.5*t*t;
    		if(hd>=y && (t-td)>=max(x/vd,(sqrt(6*hd)-sqrt(6*hd-6*y))/3))
    			r=x,ans=min(ans,t+x/vd);
    		else l=x;
    	}
    	printf("%.8f\n",ans+tf);
    }
    

    其实这题还有一种直接算答案的做法,大体思路就是把之前判断部分的式子重新写出来,然后算出每个不等式对应的约束,解完方程后再判断一下就好了,就是求解的过程略微有点麻烦,感兴趣的大佬们可以自行尝试。

    • 1

    信息

    ID
    6621
    时间
    1000ms
    内存
    128MiB
    难度
    (无)
    标签
    递交数
    0
    已通过
    0
    上传者