Physics Experiment 弹性碰撞 [POJ3684]

题意

有一个竖直的管子内有n个小球,小球的半径为r,最下面的小球距离地面h高度,让小球每隔一秒自由下落一个,小球与地面,小球与小球之间可视为弹性碰撞,让求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.

Sample Input


1 10 10 100 
2 10 10 100 
Sample Output

4.95 
4.95 10.20 

Analysis

首先这种弹性碰撞的题可以很快联想到两只蚂蚁擦肩而过的题,但是这是有半径的,是与之前视为质点的情况是不同的,如何处理?

我们根据弹性碰撞,有动量守恒和机械能守恒,得到1,2两个求撞后的速度分别为

V1'=2*(m1-m2)/(m1+m2)*V1+2*m2/(m1+m2)*V2

V2'=2*(m2-m1)/(m1+m2)*V2+2*m1/(m1+m2)*V1

那也就是1,2两个小球发生了速度交换。

我们不妨设1为下面的求,2为上面的球,那么碰撞后(相互穿越),1的重力势能瞬间增加2mgr,速度不变,2的重力势能瞬间减少2mgr,速度也不变

所以我们可以把他等效于就相当于没有半径的情况+某球下面的球的数量×2r

对于计算位置,我们由H=1/2gt2可得,t=√(2H/g)

我们令k是满足kt<=T的最大正整数,那么

ansH=    H-1/2g(T-kt)2 (k&2==0)

    H-1/2g((k+1)t-T)2 (k&2==1)

Code

 1 #include<cstdio>
 2 #include <iostream>
 3 #include <cstdio>
 4 #include <cstring>
 5 #include <cstdlib>
 6 #include <cmath>
 7 #include <vector>
 8 #include <queue>
 9 #include<map>
10 #include <algorithm>
11 #include <set>
12 using namespace std;
13 #define MM(a) memset(a,0,sizeof(a))
14 typedef long long LL;
15 typedef unsigned long long ULL;
16 const int mod = 1000000007;
17 const double eps = 1e-10;
18 const int inf = 0x3f3f3f3f;
19 const double g=10;
20 int cas,n,h,r,t,k;
21 double t0,tx,a[105],temp;
22 double solve(int x)
23 {
24      if(x<0) return h;
25      t0=sqrt(2*h*1.0/g);
26      k=int(x/t0);
27      if(k%2==0)  temp=x-k*t0;
28      else    temp=t0-(x-k*t0);
29      return h-0.5*g*temp*temp;
30 }
31 int main()
32 {
33     cin>>cas;
34     while(cas--)
35     {
36         scanf("%d %d %d %d",&n,&h,&r,&t);
37         for(int i=1;i<=n;i++)
38            a[i]=solve(t-(i-1));
39         sort(a+1,a+n+1);
40         for(int i=1;i<=n;i++)
41             printf("%.2f%c",a[i]+2*(i-1)*r/100.0,i==n?'\n':' ');//注意%s输出字符串,%c输出字符,所以这个地方不能用“”
42     }  //因为%c无法输出“”字符串
43     return 0;
44 }
View Code
posted @ 2018-07-11 15:56  iBilllee  阅读(293)  评论(0编辑  收藏  举报