题意:给一个圆心在原点的印章和圆圈范围,印章的半径Rm小于圆圈范围的半径R,扔一枚硬币,已经硬币的半径r,坐标x,y和速度矢量vx,vy,如果击中印章则被反弹,求硬币在圆圈范围内(有一点就算)的时间,硬币也可能根本不进入圆圈.
思路:首先判断硬币是否进入圆圈,已知方向向量,再加入一条从该点指向圆心的向量,如果两向量夹角为钝角,那么一定没有进入
怎么求夹角:a*b=|a|*|b|*cos(a,b); a*b=x1*x2+y1*y2;
直角是临界
为什么呢?
想想这个图形:圆形 直角?
那不就是与圆相切吗(此时的这个⚪是以R+r为半径的圆)
圆(R+r)内的还可以思考一下能不能进入R里面,但是圆外的
想都别想!
判断完这个大的范围之后,我们该判断R+r这个圆内的情况了
硬币运动轨迹方程
vy/vx就是斜率k,再带入坐标,就ok了
有了方程,我们可以求出圆心到方程的距离d(自己算去)
根据d判断硬币是否进入圆圈,是否与印章相碰撞
如果d>R+r,那么硬币无法进入圆圈范围
如果d>Rm+r,硬币进入圆圈但没有碰到印章
如果d<Rm+r,硬币碰到印章
思路就是这样,至于怎么计算~
靠你们了
代码:
#include<cstdio>
#include<cstring>
#include<math.h>
#include<iostream>
#include<iomanip>
#include<map>
#include<set>
#include<queue>
#include<stack>
#include<algorithm>
using namespace std;
#define debug(x) printf("%d***\n",x)
#define ll long long
#define maxn 5005
#define inf 0x3f3f3f3f
const double eps=1e-6;
int main()
{
double R,Rm,r,x,y,vx,vy;
while(~scanf("%lf %lf %lf %lf %lf %lf %lf",&Rm,&R,&r,&x,&y,&vx,&vy))
{
double d;
if(vx==0) //k=无穷大
d=fabs(x); //注意取绝对值
else if(vy==0) //k=0
d=fabs(y);
else
d=fabs(y-vy*x/vx)/sqrt((vy/vx)*(vy/vx)+1);
if(vx*(-x)+vy*(-y)<0) printf("0.000\n"); //另一个向量是(-x,-y);
else if(d<Rm+r)
printf("%.3lf\n",2*(sqrt((R+r)*(R+r)-d*d)-sqrt((Rm+r)*(Rm+r)-d*d))/(sqrt(vx*vx+vy*vy)));
else if(d>=R+r)printf("0.000\n");
else
printf("%.3lf\n",(sqrt((R+r)*(R+r)-d*d)*2)/(sqrt(vx*vx+vy*vy)));
}
return 0;
}