【Physics experiment】
Physics Experiment
https://ac.nowcoder.com/acm/problem/108281
此题看上去类似高中的物理题,其中用到的思维我觉得很棒;
首先抛开球的个数,单论一个球的情况
一个球到达地面所需的时间是
T时刻时,若T<=t,那么高度很简单,
当T>t时,由于和地面的碰撞是弹性碰撞,来回的过程是一样的
设k=(int)T/t(即T时刻是t的多少整数倍)
当k为奇数时,说明球处于上升过程,那么
当k为偶数时,说明球处于下降过程,那么
现在讨论2个球的情况,当俩个球在空中发生碰撞时,由于是弹性碰撞,俩个球交换速度以反向继续前进(记住是交换速度而不是原来的速度),类比poj1852的思想,可以看作俩个球并没有发生碰撞,而是穿越了对方以相同速度继续前进,由于这里球不能看作质点,我们可以假设球“瞬移了”,发生碰撞的一瞬间,位于下方的球向上瞬移了2R,位于上方的球向下瞬移了2R,即俩个球交换了位置却仍保持原速
接下来考虑T时刻的高度,我们重新定义一下h[i]=此时的高度(实际高度) - 2 * i * r
由于发生瞬移的瞬间,可以看作第i个球变成了第i+1个球,那么这个瞬间h[i]应该变成实际高度 - 2 * (i+1)*r
可知变化量为2r,和我们前面假设的一样,从而我们可以从中得出结论了
T时刻每个球的高度应该为分别假设都为一个球单独在运动得到的高度排序后分别加上2 * i * r;
代码如下:
#include <cmath> #include <algorithm> #define ll long long #define up_b upper_bound #define low_b lower_bound #define m_p make_pair #define mem(a) memset(a,0,sizeof(a)) #define IOS ios::sync_with_stdio(false);cin.tie(0);cout.tie(0) #define INF 0x3f3f3f3f #define g 10.0 #define rep(i,a,b) for(int i=a;i<=b;i++) #define per(i,a,b) for(int i=a;i>=b;i--) using namespace std; //const ll mod=1e9+7; const int maxn=1e5+5; ll read() { ll x=0,f=1;char c=getchar(); while(c<'0'||c>'9') { if(c=='-') f=-1; c=getchar(); } while(c>='0'&&c<='9') { x=x*10+c-'0'; c=getchar(); } return x*f; } int n,r,T,H; double h[10005]; double calc(int T) { if(T<0) return H; double t=sqrt(2*H/g); int k=(int)(T/t); if(k&1) { double f=k*t+t-T; return H-g*f*f/2; } else { double f=T-k*t; return H-g*f*f/2; } } void solve() { rep(i,0,n-1) h[i]=calc(T-i); sort(h,h+n); rep(i,0,n-1) printf("%.2f%c",h[i]+2*i*r/100.0,i==n-1 ? '\n':' '); } int main() { int _;_=read();while(_--) { n=read(),H=read(),r=read(),T=read(); solve(); } }