Physics Experiment(PKU No.3684)
Physics Experiment(PKU No.3684)
N個の半径R(cm)のボールで実験を行う。
上空H(m)のところに、筒を立てに設置し、ボールを入れる(下からi番目([tex: 0\leq i
アルゴリズム
R=0とすれば、Ants(PKU No.1852)と同じように、ボールがすり抜けたものとして考えられる。
衝突によってボールの順序関係は変化しないため、衝突を無視して計算した上で座標をソートすることにより、各ボールの最終的な位置を求めることができる。
R>0なら、R=0として計算した最終座標に、2Riを足すだけ(1番目→i=0)。
運動は周期的になっており、秒まで地面に向かって落下し、地面から跳ね返って頂上に到達する(v=0)時間はさらにt秒後。以降はそれを繰り返す。
が偶数なら落下運動、奇数なら上昇運動。
最後に到達した頂上 or 地面からの最終位置到達までにかかる時間は
落下運動のとき
上昇運動のとき
- 参考
コード
プログラミングコンテストチャレンジブックを見るまで、solve()中のT<0の条件が必要なことに気付かなかった。
yはについて線対称なので、
としたほうが簡単だったorz
import java.util.*; import java.lang.*; public class pku3684 { static Scanner scanner; static double g = 10.0; public static void main(String[] args) { scanner = new Scanner(System.in); new pku3684(); } pku3684(){ int C = scanner.nextInt(); while( C-- != 0 ){ int N = scanner.nextInt(); int H = scanner.nextInt(); int R = scanner.nextInt(); int T = scanner.nextInt(); double[] res = new double[N]; for(int i = 0; i < N; i++) res[i] = solve(H, T-i); Arrays.sort( res ); for(int i=0; i<N; i++){ System.out.printf( "%.2f", res[i]+2*R*i/100.0); System.out.print( (i+1==N) ? "\n" : " " ); } } } double solve(double H, int T){ if(T < 0) return H; double t = Math.sqrt( 2*H/g ); int k = (int)(T / t); double cur_t = T - k*t; if(k%2 == 0) return -1.0 / 2.0 * g * cur_t * cur_t + H; else return -1.0 / 2.0 * g * cur_t *cur_t + Math.sqrt(2.0*g*H) * cur_t; } }