题目链接
https://vjudge.net/problem/POJ-3684
题目分析
从高度为H的地方开始放球,
每一秒放一个球,
球的半径为R,
不考虑空气阻力,球直接为弹性碰撞,无动量损失。
g = 10 m / s^2
题解
根据题目,当一个球的时候,球自由落体,所需要的时间为 t = 根号下(2*H/g)可以轻松的求出
球撞击地面之后,由于没有空气阻力,并且做弹性碰撞,球会回到原处,且所花费的时间也为t。
所以当 T / t = k,
k为偶数的时候,球相当于做(T - kt)时间内的自由落体运动。
k为奇数的时候,球相当于从地面弹起,做匀减速直线运动,距离公式为
H - 0.5 * g * pow(kt + t - T, 2)
不考虑球的半径,考虑球的弹性碰撞,由于球的等质量的,可以考虑成交换速度,这里可以近似看做球没有阻碍,与之前运动相同,也就是公式不变。
如果考虑球的半径,碰撞的交换速度过程相当于每个球没有阻碍的跨越了2R的距离,要加入这样一个代价,所以要在原运动轨迹的基础之上加入一个2R。
同理,如果是第三个高度的球,则引入22R的开销,第四个球引入32R的开销,而这个开销是实际模型中无法跨越的距离,因此实际模型要减去这一段开销。
因此要在计算后的结果之上,加上这样一段距离的开销。
如果上面没有理解,就换种方法理解
之前原始模型中,我们把球看做是质点,才将碰撞后速度交换看做了之间跨越,而实际过程中,两球并不是质点,两碰球的质心之间实际上相隔了2*R的距离。
我们把这一段距离减去,在空间中缩短了这样2*R的距离,相当于质心之间距离为0,这样才可以看做质点来进行问题求解,而结果上加上模型中减去的值就可以还原真实的模型了。
AC代码
#include <iostream>
#include <algorithm>
#include <cmath>
using namespace std;
int N, H, R, T;
const int MAX_N = 100;
double y[MAX_N];
double g = 10.0;
double calc(int T)
{
if (T < 0)
{
return H;
}
double t = sqrt(2 * H / g);
int k = int(T / t);
if (k % 2 == 0)
{
return H - 0.5 * g * pow(T - k * t, 2);
}
else
{
return H - 0.5 * g * pow(k * t + t - T, 2);
}
}
void solve()
{
for (int i = 0; i < N; ++i)
{
y[i] = calc(T - i);
}
sort(y, y + N);
cout.setf(ios::fixed);
cout.precision(2);
for (int i = 0; i < N; ++i)
{
cout << y[i] + 2 * R * i / 100.0;
if (i < N - 1)
{
cout << ' ';
}
}
cout << endl;
}
int main()
{
cin.tie(0);
cout.tie(0);
ios::sync_with_stdio(false);
int TT;
cin >> TT;
while (TT--)
{
cin >> N;
cin >> H;
cin >> R;
cin >> T;
solve();
}
return 0;
}