POJ 3684 Physics Experiment(弹性碰撞)

Description
用N个半径为R厘米的求进行如下实验
在H米高的位置设置了一个圆筒,将求竖直放入(从上到下第i个球的底端距离地面高度为H+2R)。实验开始时最下面的球开始掉落,此后每一秒又有一个球开始掉落。不计空气阻力,并假设球与球或地面间的碰撞是弹性碰撞
请求出实验开始后T秒钟时每个球底端的高度。假设重力加速度g=10m/s^2
Input
第一行为用例组数t,每组用例占一行包括四个整数N,H,R,T分别表示球的个数,圆筒底端距地面距离,球半径,查询时间T
Output
对于每组用例,输出T秒后这N个球底端距离地面距离
Sample Input
2
1 10 10 100
2 10 10 100
Sample Output
4.95
4.95 10.20
Solution
首先考虑一下只有一个球的情形,从高度的位置下落需要花费时间为这里写图片描述
这样的话,在时刻T内,令k为满足kt<=T的最大整数,那么这里写图片描述
接下来再考虑多个球的情形,与Ants类似,当把两球看作质点,即R=0时就可以无视它们的碰撞,视作直接互相穿过继续运动。由于在有碰撞时球到达顺序不会发生改变,所以无视碰撞,将计算得到的坐标进行排序后,就可以知道每个球的最终位置。而R>0时只需将下方开始的第i个球在按照R=0时计算的结果上加上2Ri就好了
Code

#include<cstdio>
#include<cmath>
#include<iostream>
#include<algorithm>
using namespace std;
#define maxn 101
int M,N,H,R,T;
double g=10.0;
double y[maxn];//球的最终位置 
double solve(int T)//求出T时刻球的位置 
{
    if(T<0)//T<0说明该球还未从圆筒中下落 
        return H;
    double t=sqrt(2*H/g);
    int k=(int)(T/t);
    if(k%2==0)
    {
        double d=T-k*t;
        return H-g*d*d/2;
    }
    else
    {
        double d=k*t+t-T;
        return H-g*d*d/2;
    }
}
int main()
{
    scanf("%d",&M);
    while(M--)
    {
        scanf("%d%d%d%d",&N,&H,&R,&T);
        for(int i=0;i<N;i++)
            y[i]=solve(T-i);
        sort(y,y+N);//对坐标排序 
        for(int i=0;i<N;i++)
            printf("%.2lf%c",y[i]+2*R*i/100.0,i==N-1?'\n':' ');//按格式输出 
    }
    return 0;
}

你可能感兴趣的:(POJ 3684 Physics Experiment(弹性碰撞))