POJ 3684 Physics Experiment

Physics Experiment

Time Limit: 1000MS Memory Limit: 65536K
Total Submissions: 5009 Accepted: 1786 Special Judge

Description

Simon is doing a physics experiment with N identical balls with the same radius of R centimeters. Before the experiment, all N balls are fastened within a vertical tube one by one and the lowest point of the lowest ball is H meters above the ground. At beginning of the experiment, (at second 0), the first ball is released and falls down due to the gravity. After that, the balls are released one by one in every second until all balls have been released. When a ball hits the ground, it will bounce back with the same speed as it hits the ground. When two balls hit each other, they with exchange their velocities (both speed and direction).

Simon wants to know where are the N balls after T seconds. Can you help him?

In this problem, you can assume that the gravity is constant: g = 10 m/s2.

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

2
1 10 10 100
2 10 10 100

Sample Output

4.95
4.95 10.20

Source

POJ Founder Monthly Contest – 2008.08.31, Simon

个人觉得还是挺难的。
大概是我对物理运动问题不是很敏感,所以理解得比较困难,下面的分析供大家参考。

首先,对于一个球来说,位置很好求。假设它初始高度为T,经过时间t,所在位置可以这样求:

tripT = sqrt((double)2*H/G);//单个小球的下坠时间
double calHeight(int t){
	if(t <= 0) return H;
	int a = int(t/tripT);//a个完整的单程时间
	double t1 = t - a*tripT;
	if(a & 1){//奇数
		t1 = tripT - t1;
	}
	return H - G * t1 * t1 / 2;
}

两个小球就要涉及到碰撞了,关于“弹性碰撞”,可以参考前面的POJ1852 “Ants”(比这道题简单地多,可以先做一下练手)。

因为这些小球互相没有区别,假如说两个小球的半径都为0,因为二者会交换速度和位置,相当于两者没有发生相互作用,各自在进行各自的运动。(只不过碰撞后两者交换了身份)

但是R不为0的话呢?

R不为0的话,碰撞后两者两者就会交换位置,由于位置不一样,那么两个小球就不能当成没有发生相互作用。具体来说,假如发生了碰撞,小球的速度没有变化(我们仍假设两个小球碰撞后交换了“身份”),高度的变化是:

运动情况高度
向上运动时发生碰撞增加2R
向下运动时发生碰撞减少2R

这样问题还是很难解决:难道还要统计碰撞次数来知道它高度的变化吗?

但是,"向上运动时发生碰撞"还有一种理解方式:在所有小球中的次序增加1。
也就是说,按高度递增顺序排在第一个的小球,碰撞后排在了第二个。

同理,前面的表可以改成:

次序变化情况高度
增加1增加2R
减少1减少2R

然后就豁然开朗了: 原来这个所谓高度的变化其实从次序上就能确定。

再思考一个问题,第个小球的最小高度是多少?
答案是(i-1)*2*R。

整个问题可以理解成:第i个小球最低点是(i-1)*2*R的运动范围是[(i-1)*2*R, (i-1)*2*R + H] , 仍然可以把每个小球的运动分别看,只是最后需要按照次序来增加高度。

参考代码:

#include<iostream>
#include<cmath>
#include<vector>
#include<algorithm>
#include<cstdio>
using namespace std;

int C,N,H,R,T;
const double G = 10.0;
double tripT = 0;

int solveOneCase();
int solve(){
	scanf("%d",&C);
	for(int i = 0; i < C; ++i){
		scanf("%d%d%d%d",&N,&H,&R,&T);
		solveOneCase();
	}
	return 0;
}

double calHeight(int t){
	if(t <= 0) return H;
	int a = int(t/tripT);//a个完整的单程时间
	double t1 = t - a*tripT;
	if(a & 1){//奇数
		t1 = tripT - t1;
	}
	return H - G * t1 * t1 / 2;
}

int solveOneCase(){
	tripT = sqrt((double)2*H/G);//单个小球的下坠时间
	vector<double> locationSet;
	for(int i = 0; i < N; ++i){
		locationSet.push_back(calHeight(T-i));
	}
	sort(locationSet.begin(),locationSet.end());
	for(int i = 0; i < N; ++i){
		printf("%.2f%c",locationSet[i]+(double)2*R*i/100,i==N-1?'\n':' ');
	}
	return 0;
}


int main(){
	solve();
	return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值