POJ_3684_Physics Experiment_弹性碰撞

这个世界真奇妙


题意:

n个完全相同的半径为r的小球,最下面的小球底部距离地面高度为h,从t=0开始,每隔1妙下落一个小球,小球之间、小球与地面之间的碰撞都是弹性碰撞,求t秒后每个小球的底部高度,按照从下往上的顺序输出。


Input

The first line of the input contains one integer C (C ≤ 20) indicating the number of test cases. Each of the following lines contains four integers N, H, R, T.
1≤ N ≤ 100.
1≤ H ≤ 10000
1≤ R ≤ 100
1≤ T ≤ 10000

Output

For each test case, your program should output N real numbers indicating the height in meters of the lowest point of each ball separated by a single space in a single line. Each number should be rounded to 2 digit after the decimal point.

这题乍一看觉得好简单,然后被坑了两天

首先是第一个机智点,由于是弹性碰撞,球又全一样,所以交换速度,跟地面撞反向,经常会出现这样碰撞交换速度的情况,称之为弹性碰撞。

第二个机智点,虽然交换速度,但是两个球都是有直径的,一碰就相当于瞬移了d。但是第i个球下面有i-1个球,一个周期向下时瞬移了i-1个d,那么就相当于高度减小i-1个d,就相当于从h下落,向上时同理。这样就可以首先筛出每个球除了周期以外花费的时间,然后算出只考虑单个球的位置,然后由于最终第i个球下面肯定有i-1个球,所以最终高度应该加上i-1个d

然后就是第三个机智点,坑我开了5个vim对拍。考虑两个球碰撞,虽然相当于两个球交换了位置速度不变,但是下面的球编号仍然比上面的球大,所以下面的球最后加的d的数量必然比上面的小,但如果这时候我们查询结果怎么办?这显然不合理。最终的排序应该根据没加d的情况排序,然后再加上对应的d。


代码如下:

#include
#include
#include
#include
#include
#include
using namespace std;
#define mxn 110
int n;
double h,r,t;
double loc[mxn];
const double g=10.0;
int main(){
	int cs;
	scanf("%d",&cs);
	while(cs--){
		scanf("%d%lf%lf%lf",&n,&h,&r,&t);
		r/=100;
		double tt=sqrt(2*h/g)*2;
		for(int i=0;i


你可能感兴趣的:(POJ_3684_Physics Experiment_弹性碰撞)