传送门
There's a round medal fixed on an ideal smooth table, Fancy is trying to throw some coins and make them slip towards the medal to collide. There's also a round range which shares exact the same center as the round medal, and radius of the medal is strictly less than radius of the round range. Since that the round medal is fixed and the coin is a piece of solid metal, we can assume that energy of the coin will not lose, the coin will collide and then moving as reflect.
Now assume that the center of the round medal and the round range is origin ( Namely (0, 0) ) and the coin's initial position is strictly outside the round range. Given radius of the medal Rm, radius of coin r, radius of the round range R, initial position (x, y) and initial speed vector (vx, vy) of the coin, please calculate the total time that any part of the coin is inside the round range.
Please note that the coin might not even touch the medal or slip through the round range.
Input
There will be several test cases. Each test case contains 7 integers Rm, R, r, x, y, vx and vy in one line. Here 1 ≤ Rm < R ≤ 2000, 1 ≤ r ≤ 1000, R + r < |(x, y)| ≤ 20000, 1 ≤ |(vx, vy)| ≤ 100.
Output
For each test case, please calculate the total time that any part of the coin is inside the round range. Please output the time in one line, an absolute error not more than 1e-3 is acceptable.
Sample Input
5 20 1 0 100 0 -1
5 20 1 30 15 -1 0
Sample Output
30.000
29.394
题意:
给定的两个同心圆,他们的的圆心都是原点(0,0),现在给一枚硬币,还有这枚硬币移动的向量表示,现在让求硬币在圆上运动的时间(这个硬币撞到里面的圆的时候会反弹)
题解:
暂且定半径为Rm的圆为1,半径为R的圆为2,现在要计算硬币在圆里面运动的时间长度
在刚开始做的时候采用的是求硬币运动方程的方法来做的,这个时候考虑的是三种情况
1、运动轨迹跟2无交点(外离)
2、运动轨迹跟2有交点但是跟1没有交点
3.运动轨迹跟1有交点
不过这里要注意的一点就是,什么时候才能算是有交点:
在两个圆相切的时候他们就应该开始计算了!
不过,这道题让算的是时间
既然是让算时间,那么我们就采用参数方程来表示硬币的圆心所在的位置
{ x=x+vx*t;
{ y=y+vy*t;
给出了一个点,我们现在结合刚才说的通过轨迹方程的做法,把一维的图形转换成点到点的模型来处理
硬币圆心到原点的距离可以类比为原点到轨迹方程的距离,这样问题就又被分为三部分了
计算△,通过△判断与圆的关系
计算时间t,如果说时间t是负数,那么就说明现在的移动方向是反方向的,也就是说,硬币是不会往圆上走的,这里很重要,因为用第一种方法做的时候少考虑了这么一种情况WA了很多次。
#include<cstdio>
#include<algorithm>
#include<iostream>
#include<cmath>
using namespace std;
double a,b,c,o,t1,t2,t3;
int main()
{
double Rm,R,r,x,y,vx,vy;
while(~scanf("%lf %lf %lf %lf %lf %lf %lf",&Rm,&R,&r,&x,&y,&vx,&vy))
{
a=vx*vx+vy*vy;
b=2*(x*vx+y*vy);
c=x*x+y*y-(R+r)*(R+r);//现在判断跟外圆的交点
o=b*b-4*a*c;
if(o<=0)
{
printf("0.000\n");
}
else
{
//现在代表的是有交点
t1=(b*(-1)-sqrt(o))/(2*a);
if(t1<=0)
{
printf("0.000\n");
}
else
{
//现在判断跟里面的有没有交点
t2=(((-1)*b)+sqrt(o))/(2*a);
//现在判断跟Rm有没有交点,如果没有的话
c=x*x+y*y-(Rm+r)*(Rm+r);
o=b*b-4*a*c;
if(o<=0)
{
printf("%.3lf\n",t2-t1);
}
else
{
t3=((-b)-sqrt(o))/(2*a);
printf("%.3lf\n",2*(t3-t1));
}
}
}
}
return 0;
}