有N个半径为R厘米的球,进行如下物理实验:
在高处为H米的地方有一个圆筒,把球都垂直放在里面,第i个球底端距离地面的高度为H+2*R*i,实验开始最下面的求先掉落,其他求保持位置不变,
然后每秒放一个球,不计空气阻力,都是弹性碰撞,要求T秒后所有球的位置。
这样来考虑:在第二个,第三个球下面连接n-1个“虚拟球”,速度与原球一致,而碰撞只有在最底部的虚拟球与虚拟球底边接触时才发生,效果和实际求碰撞一致。
所以每当发生碰撞时两个底部的虚拟球交换速度,可以当做互相穿过,互不影响,只是每个一串球最底部编号要按照高度重新分配(实际情况中球的次序是永远不会改变的)。
而实际的那个球肯定是和对应的底部虚拟球保持2R*i的高度差(如第二个球肯定和第二号虚拟球连接)所以可以获得递推式:
每串求最底部按个虚拟球高度肯定为H,所以相当于不受任何影响的自由落体,而实体球在其基础上再增加2R*i的高度差。
题源来自《挑战程序竞赛》第二版158页,书中的解释不太明确,有点含糊,所以这里给出了以上证明,不知道是否有更好的证明方式。
//
// 158_Physics experiment.cpp
// changlle
//
// Created by user on 1/10/16.
// Copyright (c) 2016 user. All rights reserved.
//
#include <iostream>
#include <math.h>
using namespace std;
int N=2;
int H=10;
int R=10;
int T=100;
const double g=10.0;
double y[2];
double calc(int T) {
if (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;
}
}
void solve() {
for (int i=0;i<N;i++) {
y[i]=calc(T-i);
}
sort (y,y+N);
for (int i=0;i<N;i++)
{
y[i]=y[i]+2*R*i/100.0;
cout<<y[i]<<" ";
}
}
int main() {
solve();
return 0;
}