C语言网 蓝桥杯训练 1075 台球碰撞

9 篇文章 0 订阅

在这里插入图片描述
在这里插入图片描述
样例输入

100 100 80 10 5 90 2 23
110 100 70 10 5 180 1 9999
0 0 0 0 0 0 0 0

样例输出

80.00 56.00
71.00 10.00

思路
将二维的运动转换为一维的运动

这个问题涉及到球在二维平面内的受边界限制的斜向运动,在写程序之前有几个问题要考虑:
  a.我们最终所求的是球心坐标,而球与球桌碰撞时实际上是球的边界与球桌边界发生碰撞,并不是球心发生的碰撞,因此在研究这个问题时为了简化模型,可以将球转化为球心质点,并建立新的坐标系来研究球心的运动。
  我们以原坐标系的点(R,R)作为新坐标系的原点(0,0)建立新坐标系,这样新坐标系中球心运动范围的长l和宽w都会相对于原先的L,W分别减小2R,如图所示:
在这里插入图片描述
b.现在我们在二维平面内的新坐标系下研究球心质点的运动。由于题目给出的角度a是任意的,球可能是向任意方向运动的,因此这里我们利用三角函数将球的运动分解为水平方向和竖直方向,可以看出在整个运动过程中球在水平和竖直方向上的运动速率(这里不指带有方向的速度,速度的方向可能在在碰撞后掉头)是恒定不变的。

c.速度分解后这个问题便可以转化为一维数轴上的边界碰撞问题。我们假设一个数轴上有一个质点在运动,它的运动范围是[0,10],假设初始坐标是3,现在它可能向左或者向右进行运动,我们在已知它的运动位移的情况下来求解它的最终位置:
在这里插入图片描述
这里为了方便处理,我们做一个转化,把它的初始位置 3 看做是在这次运动前,是已经从原点出发向右移动了3个单位。看成从原点出发的好处是,我们可以求出它相对于原点的总运动位移后 直接加绝对值来将总位移直接全部转化为正值。
(解释一下:如果质点从原点出发,那么它发生5的位移和发生-5的位移是没有区别的,因为如果一开始就从原点向左走,立马会反弹为向右走。)
  举个例子:假设质点从 3 开始发生-27的位移,也就相当于是从原点开始发生了(-27+3)=(-24)的位移,也就相当于从原点开始发生了24的总位移。
  而数轴上质点的移动范围只有10,我们注意到如果质点发生10x2=20的位移,那么质点将会回到初始位置,因此在某个方向上边界范围的两倍实际上是一个运动周期,发生 24 的位移也就是发生 4 的位移。因此在这里例子里最终坐标为4。
  所以我们只需要讨论在总位移中去除了若干个周期(本例子中的20)后的剩余位移。
  若剩余的位移小于一个边界长度,例如这个例子中的边界长度为10,那么最终坐标就等于剩余位移大小;若剩余位移处于一个边界长度和两个边界长度之间,那么不难发现最终坐标就等于两个边界长度-剩余位移(例如从原点开始发生了17的位移,最终坐标为20-17=3)

综上所述:假设初始坐标为 x ,移动位移为 s ,边界长度为 L ,那么求解最终坐标的方法就是:先求出转化后的从原点出发的总位移 Dx,Dx=fabs(x+s),之后若 Dx 大于 2L 则 Dx-=2L 直到 Dx小于2L,最后若 Dx小于L 则 Dx 即最终坐标,若 Dx介于2L和L之间 ,那么最终坐标为 2L-Dx 。
  我们将这个方法推广到之前已经被分解过的二维平面运动中,即可分别求出x和y方向上的球心运动最终坐标(新坐标系中的),最后输出时再加上R即可转换回原坐标系中的坐标。

代码

#include<stdio.h>
#include<math.h>

int main(){
	double L,W,x,y,R,a,v,s;
	
	double Dx = 0,Dy = 0;
	
	for(int l,w,x0,y0;;){
		scanf("%lf%lf%lf%lf%lf%lf%lf%lf",&L,&W,&x,&y,&R,&a,&v,&s);
		if(L==0&&W==0&&x==0&&y==0){
			break; //输入终止条件 
		}
		
		a = a/180.0 * acos(-1); //角度转弧度,arcos(-1)==PI
		
		//球转换为质点,缩小球台建立新坐标系 
		l = L - 2*R;
		w = W - 2*R;
		x0 = x-R; 
		y0 = y - R; 
		
		Dx = fabs(cos(a)*v*s +x0);
		
		Dy = fabs(sin(a)*v*s + y0);
		
		//求出在新坐标系中质点相对左下角原点的偏移量Dx,Dy
		for(;Dx>2*l;){
			Dx -= 2*l;
		} 
		
		for(;Dy>2*w;){
			Dy -= 2*w;
		}
		
		//去除偏移量中的可能存在的周期部分
		if(Dx>l&&Dx<2*l) Dx = 2*l - Dx;
		else;
		
		if(Dy>w&&Dy<2*w) Dy = 2*w - Dy;
		else;
		//求出新坐标系中质点的最终坐标
		
		printf("%.2lf %.2lf\n",Dx + R,Dy + R); //将坐标加上R转换为原坐标系坐标输出 
	}
	
	return 0;
}
  • 2
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值