hdu 4793 Collision
题目链接//http://acm.hdu.edu.cn/showproblem.php?pid=4793
Problem Description
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
题目大意:太长自己看
思路:起初我是想由x,y确定一条直线,判断该直线是否过大圆,然而,忽略了一个很严重的问题,硬币可能不会往大圆方向弹,即使所确定的直线过大圆硬币也可能不会过大圆。
直到我改变了写法才意识到这个问题,新的写法是建立硬币中心点的坐标与时间的函数即
x(t)=x+vx*t
y(t)=y+vy*t
在分别与两个圆联立:
(x+tvx)2+(y+vy*t)2=(R+r)2-------1
(x+tvx)2+(y+vy*t)2=(Rm+r)2----2
不过圆的情况由方程一无解或只有一个解或t<0(易知只需判断方程一的某一解是否为正即可)
若只过大圆答案即方程一的两解之差|t1-t2|有韦达定理为sqrt(b2-4ac)/a
若与小圆相撞,答案则为|t1-t2|-|t21-t22|方程一的两解之差减方程二的两解之差
因为硬币反弹后的轨迹与之前的轨迹长度相同,倘若能穿过小圆,则穿过后的轨迹长度也相等,故直接用穿过大圆的时间减去穿过小圆的时间
代码如下:
#include<bits/stdc++.h>
#define ll long long
#define mod 1000003
#define f(x) (x)*(x)
using namespace std;
//const double pi=atan(1)*4;
const double eps = 1e-7;
inline int dcmp(double x) {
if (fabs(x) < eps) return 0;
else return x < 0 ? -1 : 1;
}
double rm,R,r,x,y,vx,vy,ans;
int main(){
while(cin>>rm>>R>>r>>x>>y>>vx>>vy){
R+=r;
r+=rm;//直接把大圆小圆的半径增加r,方便写代码
double a=f(vx)+f(vy),b=2*(x*vx+y*vy);
double c1=x*x+y*y-R*R,c2=x*x+y*y-r*r;
double dt1=b*b-4*a*c1,dt2=b*b-4*a*c2;
double t3 = (-b + sqrt(dt1)) / (2 * a);
if(dcmp(dt1)<=0){
ans=0;
}else{
if(t3<0){
ans=0;
}else{
if(dcmp(dt2)<=0){
ans=sqrt(dt1)/a;
}else{
ans=sqrt(dt1)/a-sqrt(dt2)/a;
}
}
}
printf("%.3f\n",ans);
}
}