zoukankan      html  css  js  c++  java
  • Greedy:Physics Experiment(弹性碰撞模型)(POJ 3848)

                

                      物理实验

      题目大意:有一个与地面垂直的管子,管口与地面相距H,管子里面有很多弹性球,从t=0时,第一个球从管口求开始下落,然后每1s就会又有球从球当前位置开始下落,球碰到地面原速返回,球与球之间相碰会发生完全弹性碰撞(各自方向改变,速率变为相碰时另一个球的速率)问最后所有球的位置?

      这一题又是一道弹性碰撞模型的题目,和Liner World有点像,但是这一题不要求输出球的名字,而是要你求得各个球的高度

      这道题我们只用明白一个道理就很方便了:

        首先我们来看一个球的情况:

     一个球从H的高度下落,碰到地面原速返回,那么他在t时刻的位置由下列方程决定:

        t=sqrt(2*H/g);

        k=(int)(T/t);

        Hi=H-(T-k*t)*(T-k*t)*g/2;    (当K是偶数)

        Hi=H-(k*t+t-T)*(k*t+t-T)*g/2;  (当K是奇数) 

      如果有两个球:

      如果第一个球没有碰地,那么两个球的高度将由Hi=H-(T-k*t)*(T-k*t)*g/2唯一确定

      如果第一个球碰地了,那么在接下来的某一时刻两个球一定会相碰且交换速度,可以看成是擦身而过,但问题还没完,如果相碰后不再相碰,要确定高度,那么究竟怎么确定呢?

      我们知道因为各个球可以看成独立的,根据题意,第2个球的高度应该要加上两个球的半径并除以100.0(单位是cm看清楚!),然后交换速度过后我们虽然2和1交换了状态,但是状态不变,我们还是可以把他们当成一个球看,但是同时注意,这两个球是有半径的!(一开始我没有想到半径打死都想出来为什么,模拟了一下才明白),最后答案为从低到高排列的小球逐次加上0和2r的高度即可(如果存在交换一定要排列,否则两个球就会重叠了就不对了)。

      把上面这两种情况推广到多个球,我们就可以得到解决方法了

      

     1 #include <iostream>
     2 #include <algorithm>
     3 #include <functional>
     4 #include <math.h>
     5 
     6 using namespace std;
     7 
     8 double cal(const double, const double, const double);
     9 const double g = 10.0;
    10 static double h[101];
    11 
    12 int main(void)//很巧妙的一道物理模型题
    13 {
    14     int case_sum, N;
    15     double H, R, T, seg_t;
    16     scanf("%d", &case_sum);
    17 
    18     while (case_sum--)
    19     {
    20         scanf("%d%lf%lf%lf", &N, &H, &R, &T);
    21         seg_t = sqrt(2 * H / g); 
    22 
    23         for (int i = 0; i < N; i++)
    24             h[i] = cal(seg_t, T - i, H);//每一个间隔减少1s
    25         sort(h, h + N);
    26         for (int i = 0; i < N; i++)
    27             printf("%.2f ", h[i] + 2 * R*i / 100.0);
    28         printf("
    ");
    29     }
    30     return EXIT_SUCCESS;
    31 }
    32 
    33 double cal(const double t, const double T, const double H)
    34 {
    35     if (T < 0)
    36         return H;//相当于还没开始下落就直接
    37     int k =(int)(T / t);//看究竟是上升阶段还是下降阶段。
    38     if (k % 2 == 0)//下降阶段
    39         return H - g*(T - k*t)*(T - k*t) / 2;
    40     else
    41         return H - g*(k*t + t - T)*(k*t + t - T) / 2;
    42 
    43 }

      

          

  • 相关阅读:
    转载:通过Servlet生成验证码
    转载:web工程中URL地址的推荐写法
    使用Git上传本地项目代码到github
    $watch 和 $apply
    平时用的sublime插件
    zTree.js
    js
    npm install详解
    git
    git基础
  • 原文地址:https://www.cnblogs.com/Philip-Tell-Truth/p/5175889.html
Copyright © 2011-2022 走看看