原题链接:poj3684 Physics Experiment
题意:高H米处设置一个竖直圆筒,N个小球竖直在圆筒中,从下向上数第i个小球距离地面高度是H+2*R*i
最下面球开始落下,之后每秒落下一个球,不计阻力,碰撞都是弹性碰撞,求T秒之后每个小球距地面高度
输入 N H R T (H单位是米,R单位是厘米,T单位是秒)
输出 每个小球距地面高度(从下往上,单位用米)
/*
如果就一个球:从H到地面时间t=sqrt(2H/g),设k是满足kt<=T的最大整数,其最终高度y有两种情况:
1.k为偶数,即球向下落:y=H-1/2*g*pow(T-kt, 2);
2.k为奇数,即球向上升:y=H-1/2*g*pow(kt+t-T, 2);
多个球的时候,如果相互碰撞,两球速度交换,可看作直接穿过,不过球的顺序实际是不变的(只是速度交换并没有穿过)
所以最后排序后加上每个球下面小球的直径就是最终高度
速度交换:1.由动量定理:m*v1+m*v2=m*v1'+m*v2' 得v1+v2=v1'+v2'
2.由动能定理:1/2*m*v1^2+1/2*m*v2^2=1/2*m*v1'^2+1/2*m*v2'^2 得 v1^2+v2^2=v1'^2+v2'^2
两式联立得到:v1=v2',v2=v1'(速度交换)所以两球速度会交换
*/
#include <cstdio>
#include <cmath>
#include <algorithm>
using namespace std;
const int MAX_N = 101;
const double g = 10.0;//重力加速度
int N, H, R, T; //输入
double y[MAX_N], t; //球的最终高度和第一次落地时间
double calc(int T){ //求出T时刻球的位置
if(T < 0) return H; //还没开始落的情况
int k = (int)(T / t); //k是满足kt<=T的最大整数
//如果k为偶数,小球是向下落,否则小球是向上升的
double dt = k & 1 ? k * t + t - T : T - k * t;
return H - g * dt * dt / 2;
}
int main(){
int C;
scanf("%d", &C);
while(C --){
int i;
scanf("%d%d%d%d", &N, &H, &R, &T);
t = sqrt(2.0 * H / g);
for(i = 0;i < N;i ++){
y[i] = calc(T - i); //不同球时间不同
}
sort(y, y + N);
for(i = 0;i < N;i ++){ //高度加上下面球的直径
printf("%.2lf%c", y[i] + 2 * i * R / 100.0, i + 1 == N ? '\n' : ' ');
}
}
return 0;
}