Description
Particle colliders are difficult to build and experiments are costly to run. Before running any real experiments it is better to do a simulation to test out the ideas first. You are required to write a very simple simulator for this problem.
There are only three particles in this system, and all particles are confined to an infinite plane so that they can be modelled as circles. Their locations are specified only by the xi and yi coordinates of their centers (1 ≤ i ≤ 3). All three particles have the same radius r, and are initially stationary.
We are given a vector (xv, yv) specifying the direction particle 1 will move when the experiment starts. When particle i hits particle j, particle j will start moving in the direction perpendicular to the tangent at the point of the contact, away from particle i. Particle i will cease to exist and be converted to radiation. A moving particle that does not hit another will continue moving indefinitely.
There are a number of possible scenarios your simulator should identify:
- item particle 1 hits particle 2, which in turns hits particle 3;
- item particle 1 hits particle 3, which in turns hits particle 2;
- item particle 1 hits particle 2, which moves indefinitely;
- item particle 1 hits particle 3, which moves indefinitely;
- item particle 1 moves indefinitely.
Input
The input contains four lines. The first three lines each contains two integers xi and yi (|xi|,|yi|≤1000), describing particles 1, 2, and 3 in this order. The fourth line contains three integers xv, yv, and r (|xv|,|yv|≤1000, 0 < r ≤ 50).
You may assume that no two particles touch or overlap initially, and that the distance between the centers of particles 2 and 3 is greater than 4r.
Output
Output a single integer giving the number (1--5) identifying the scenarios described above.
Although you should take care of your calculations, it is guaranteed that the outcome would not change if the initial vector (xv, yv) is rotated by one degree either way.
Sample Input
0 0 50 45 91 50 42 50 10 0 0 50 50 141 50 41 50 10 0 0 50 50 131 50 100 50 10
Sample Output
1 3 4
Hint
Source
rmc17
题目大意:
给三个圆盘,给第一个圆盘一个初速度,问运动的情况:
1碰2,然后2碰3,输出数字1
1碰3,然后3碰2,输出数字2
1碰2,然后2一直走下去,输出数字3
1碰3,然后3一直走下去,输出数字4
1一直走下去,输出数字5
题解:
解法一:
数学,判断两圆会不会相交,圆1 的方程是x=x1+vx*t,y=y1+vy*t,若(x-x2)2+(y-y2)2<=r2,说明会相撞,相撞时,可以解出t,所有坐标都解出,再利用角度关系确定新的运动方向,再判断是否会相撞。
解法二:
计算几何,圆2的圆心到圆1发出射线的距离,大于2r,则不会相交,反之相交。
如图,求出θ,在用向量旋转确定新的方向,再判断相交情况。
代码:
#include<cstdio>
#include<iostream>
#include<cmath>
#include<algorithm>
#define pi 3.141592653589793
using namespace std;
const double eps=1e-6;
int dcmp(double x){if (fabs(x)<eps)return 0;else return x<0?-1:1;}
double r;
struct Point
{
double x,y;
Point(double x=0,double y=0):x(x),y(y){ }
void read(){scanf("%lf%lf",&x,&y);}
};
typedef Point Vector;
Vector operator + (Vector a,Vector b){return Vector(a.x+b.x,a.y+b.y);}
Vector operator - (Vector a,Vector b){return Vector(a.x-b.x,a.y-b.y);}
double Dot(Vector a,Vector b){return a.x*b.x+a.y*b.y;} //点积
double Length(Vector a){return sqrt(Dot(a,a));}
double Cross(Vector a,Vector b){return a.x*b.y-a.y*b.x;} //叉积
Vector Rotate(Vector a,double rad)// 向量 a 逆时针旋转 rad
{return Vector(a.x*cos(rad)-a.y*sin(rad),a.x*sin(rad)+a.y*cos(rad));}
//点p到直线ab的距离
double PTL(Point p,Point a,Point b)
{
Vector v1=b-a,v2=p-a;
return fabs(Cross(v1,v2)/Length(v1));
}
bool check(Point x,Point y,Point z)
{
if (dcmp(PTL(z,x,x+y)-r-r)>=0)return true;
if (dcmp(PTL(z,x,x+y)-r-r)<0 && dcmp(Dot(y,z-x))<0)return true;
return false;
}
int main()
{
Point a[5];
while(~scanf("%lf%lf",&a[1].x,&a[1].y))
{
a[2].read();a[3].read();a[0].read(); scanf("%lf",&r);
if (check(a[1],a[0],a[2]) && check(a[1],a[0],a[3]))puts("5");else
if (check(a[1],a[0],a[2]) && !check(a[1],a[0],a[3]) ||
(!check(a[1],a[0],a[2]) && !check(a[1],a[0],a[3])&& Length(a[1]-a[2])>Length(a[1]-a[3])))
{
double d=PTL(a[3],a[1],a[1]+a[0]);
double ang=asin(d/r/2);
if (dcmp(Cross(a[3]-a[1],a[0]))>0)a[0]=Rotate(a[0],pi*2-ang);else
a[0]=Rotate(a[0],ang);
if (check(a[3],a[0],a[2]) )puts("4");else puts("2");
}else
if (!check(a[1],a[0],a[2]) && check(a[1],a[0],a[3]) ||
(!check(a[1],a[0],a[2]) && !check(a[1],a[0],a[3])&& Length(a[1]-a[2])<Length(a[1]-a[3])))
{
double d=PTL(a[2],a[1],a[1]+a[0]);
double ang=asin(d/r/2);
if (dcmp(Cross(a[2]-a[1],a[0]))>0)a[0]=Rotate(a[0],pi*2-ang);else
a[0]=Rotate(a[0],ang);
if (check(a[2],a[0],a[3]) )puts("3");else puts("1");
}
}
}