ZOJ - 3728
题目大意:
一个奖牌放在原点,奖牌外面有一个圈,一个硬币在光滑平面上移动,如果撞到奖牌就会反弹。求硬币在圈内的总时间。
注意反弹就是原路返回,reflect......
这场区域赛的题干一直让人很不舒服,不知道是出题人的锅还是我自己的锅......
题解:
①硬币圆心的运动轨迹
, 计算它与原点的距离,
是一元二次方程,如果
,说明硬币会和大圆有相交,求出的两个解之差t2-t1就是硬币在大圆内的时间。
②计算
,如果
,说明硬币不会和奖牌有碰撞,答案就是t2-t1。如果
,求出两个解为tt1,tt2,答案就是(t2-t1)-(tt2-tt1)。
有2个WA点:
①给出的速度方向可能正好和奖牌在的方向反向,这时永远不会相交,求出来的t1,t2就会有负的,此时要判断一下。
②读Rm,R,r,x,ym,vx,vy时,不能用int读,后面的4*(x*vx+y*vy)*(x*vx+y*vy)会爆int的,用double读。
#include<bits/stdc++.h>
#include<cstring>
using namespace std;
#define ll long long
int main()
{
double Rm,R,r,x,y,vx,vy;
double ans;
cout<<fixed<<setprecision(4);
while(cin>>Rm>>R>>r>>x>>y>>vx>>vy)
{
double del=4*(x*vx+y*vy)*(x*vx+y*vy)-4*(vx*vx+vy*vy)*(x*x+y*y-R*R-2*R*r-r*r);
if(del<=0.0)
{
cout<<0.0<<endl;
continue;
}
double t1=(-2*(x*vx+y*vy)-sqrt(del))/2*(vx*vx+vy*vy);
double t2=(-2*(x*vx+y*vy)+sqrt(del))/2*(vx*vx+vy*vy);
if(t1<0.0 || t2<0.0)
{
cout<<0.0<<endl;
continue;
}
double del1=4*(x*vx+y*vy)*(x*vx+y*vy)-4*(vx*vx+vy*vy)*(x*x+y*y-Rm*Rm-2*Rm*r-r*r);
if(del1<=0.0)
ans=sqrt(del)/(vx*vx+vy*vy);
else
ans=(sqrt(del)-sqrt(del1))/(vx*vx+vy*vy);
cout<<ans<<endl;
}
return 0;
}