解题思路:
简单来说,球的起步可以分成8个大方向,分别为0°、0°-90°、90°、90°-180°、180°、180°-270°、270°、270°-360°;先说水平和竖直方向,球的运动轨迹单一,只是横向或竖向移动,碰壁返回,只会在一个方向上产生分速度;而其余4种情况球的运动轨迹相对复杂些,每种情况均会产生两种方式的碰撞反弹,比如a<90°时,可能会先在右侧碰壁往左上反弹,又或者可能先在上壁碰撞往右下反弹,每种情况只需确定好反射角就好;而产生碰撞的时候有一个方向的坐标便可以确定下来,从而顺藤摸瓜求出路径以及另一个坐标。如此反复直至v*s=0结束。
注意事项:
三角函数sin,cos,tan参数为弧度制的度数。
如果要用到pi,精度要写高点。
弧度=角度*pi/180。
参考代码:
//问题 1075: 台球碰撞
#include<stdio.h>
#include<math.h>
int main()
{
//const double pi=3.141592653; //定义pi的值
double L,W,x,xx,y,yy,R,a,v,vv,s,aa; //xx,yy,vv,表示碰壁前各个方向的分路程。
scanf("%lf%lf%lf%lf%lf%lf%lf%lf",&L,&W,&x,&y,&R,&a,&v,&s);
while(L!=0||W!=0||x!=0||y!=0||R!=0||a!=0||v!=0||s!=0)
{
for(v=v*s;v>0;)
{
if(0<a&&a<90)
{
aa = a*asin(1)*2/180; //度数转化成弧度制的角度
yy=v*sin(aa);
xx=v*cos(aa);
if((yy+y+R>=W)||(xx+x+R>=L))
{
if(yy+y+R>=W) //碰上边
{
yy=W-R-y;
y=W-R;
xx=yy/tan(aa);
x+=xx;
v-=yy/sin(aa);
a=360-a;
}
else //碰右边
{
xx=L-R-x;
x=L-R;
yy=xx*tan(aa);
y+=yy;
v-=yy/sin(aa);
a=180-a;
}
}
else
{
y+=yy;
x+=xx;
v-=v;
}
}
else if(a==90)
{
if(v+y+R>=W)
{
v-=W-y-R;
a=270;
y=W-R;
}
else
{
y+=v;
v-=v;
}
}
else if(90<a&&a<180)
{
aa = a*asin(1)*2/180;
yy=v*sin(aa);
xx=-v*cos(aa);
if((yy+y+R>=W)||(x-R-xx<=0))
{
if(yy+y+R>=W) //碰上边
{
aa = (180-a)*asin(1)*2/180;
yy=W-R-y;
y=W-R;
xx=yy/tan(aa);
x-=xx;
v-=yy/sin(aa);
a=360-a;
}
else //碰左边
{
aa = (180-a)*asin(1)*2/180;
xx=x-R;
x=R;
yy=xx*tan(aa);
y+=yy;
v-=yy/sin(aa);
a=180-a;
}
}
else
{
y+=yy;
x-=xx;
v-=v;
}
}
else if(a==180)
{
if(x-v<=R)
{
v-=x-R;
a=0;
x=R;
}
else
{
x-=v;
v-=v;
}
}
else if(180<a&&a<270)
{
aa = a*asin(1)*2/180;
yy=-v*sin(aa);
xx=-v*cos(aa);
if((y-R-yy<=0)||(x-R-xx<=0))
{
if(y-R-yy<=0) //碰下边
{
aa = (a-180)*asin(1)*2/180;
yy=y-R;
y=R;
xx=yy/tan(aa);
x-=xx;
v-=yy/sin(aa);
a=360-a;
}
else //碰左边
{
aa = (a-180)*asin(1)*2/180;
xx=x-R;
x=R;
yy=xx*tan(aa);
y-=yy;
v-=xx/cos(aa);
a=540-a;
}
}
else
{
y-=yy;
x-=xx;
v-=v;
}
}
else if(a==270)
{
if(y-v<=R)
{
v-=y-R;
a=90;
y=R;
}
else
{
y-=v;
v-=v;
}
}
else if(270<a&&a<360)
{
aa = a*asin(1)*2/180;
yy=-v*sin(aa);
xx=v*cos(aa);
if((y-R-yy<=0)||(x+R+xx>=L))
{
if(y-R-yy<=0) //碰下边
{
aa = (360-a)*asin(1)*2/180;
yy=y-R;
y=R;
xx=yy/tan(aa);
x+=xx;
v-=yy/sin(aa);
a=360-a;
}
else //碰右边
{
aa = (360-a)*asin(1)*2/180;
xx=L-R-x;
x=L-R;
yy=xx*tan(aa);
y-=yy;
v-=yy/sin(aa);
a=540-a;
}
}
else
{
y-=yy;
x+=xx;
v-=v;
}
}
else //0°
{
if(v+x+R>=L)
{
v-=L-x-R;
a=180;
x=L-R;
}
else
{
x+=v;
v-=v;
}
}
}
printf("%.2lf %.2lf\n",x,y);
scanf("%lf%lf%lf%lf%lf%lf%lf%lf",&L,&W,&x,&y,&R,&a,&v,&s);
}
return 0;
}
0.0分
0 人评分
C语言网提供由在职研发工程师或ACM蓝桥杯竞赛优秀选手录制的视频教程,并配有习题和答疑,点击了解:
一点编程也不会写的:零基础C语言学练课程
解决困扰你多年的C语言疑难杂症特性的C语言进阶课程
从零到写出一个爬虫的Python编程课程
只会语法写不出代码?手把手带你写100个编程真题的编程百练课程
信息学奥赛或C++选手的 必学C++课程
蓝桥杯ACM、信息学奥赛的必学课程:算法竞赛课入门课程
手把手讲解近五年真题的蓝桥杯辅导课程
发表评论 取消回复