On an infinite smooth table, there's a big round fixed cylinder and a little ball whose volume can be ignored.
Currently the ball stands still at point AA, then we'll give it an initial speed and a direction. If the ball hits the cylinder, it will bounce back with no energy losses.
We're just curious about whether the ball will pass point BB after some time.
Currently the ball stands still at point AA, then we'll give it an initial speed and a direction. If the ball hits the cylinder, it will bounce back with no energy losses.
We're just curious about whether the ball will pass point BB after some time.
Every test case contains three lines.
The first line contains three integers OxOx, OyOy and rr, indicating the center of cylinder is (Ox,Oy)(Ox,Oy) and its radius is rr.
The second line contains four integers AxAx, AyAy, VxVx and VyVy, indicating the coordinate of AA is (Ax,Ay)(Ax,Ay) and the initial direction vector is (Vx,Vy)(Vx,Vy).
The last line contains two integers BxBx and ByBy, indicating the coordinate of point BB is (Bx,By)(Bx,By).
⋅⋅ 1 ≤ TT ≤ 100.
⋅⋅ |OxOx|,|OyOy|≤ 1000.
⋅⋅ 1 ≤ rr ≤ 100.
⋅⋅ |AxAx|,|AyAy|,|BxBx|,|ByBy|≤ 1000.
⋅⋅ |VxVx|,|VyVy|≤ 1000.
⋅⋅ Vx≠0Vx≠0 or Vy≠0Vy≠0.
⋅⋅ both A and B are outside of the cylinder and they are not at same position.
2 0 0 1 2 2 0 1 -1 -1 0 0 1 -1 2 1 -1 1 2
Case #1: No Case #2: Yes
#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>
#include <iostream>
using namespace std;
#define maxn 100005
const double eps = 1e-5;
const double INF = 1e20;
const double pi = acos (-1.0);
int dcmp (double x) {
if (fabs (x) < eps) return 0;
return (x < 0 ? -1 : 1);
}
///*************点
struct Point {
double x, y;
Point (double _x = 0, double _y = 0):x(_x), y(_y) {}
bool operator < (const Point &b) const {
return (dcmp (x-b.x) == 0 ? dcmp (y-b.y) < 0 : x < b.x);
}
Point operator + (const Point &b) const {
return Point (x+b.x, y+b.y);
}
Point operator - (const Point &b) const {
return Point (x-b.x, y-b.y);
}
Point operator * (double a) {
return Point (x*a, y*a);
}
Point operator / (double a) {
return Point (x/a, y/a);
}
double len2 () {///返回长度的平方
return x*x + y*y;
}
double len () {///返回长度
return sqrt (len2 ());
}
Point change_len (double r) {///转化为长度为r的向量
double l = len ();
if (dcmp (l) == 0) return *this;///零向量返回自身
r /= l;
return Point (x*r, y*r);
}
};
///计算两个向量的叉积
long double cross(const Point &a,const Point &b){
return a.x*b.y-a.y*b.x;
}
///计算两个点的点积
long double dot(const Point &a,const Point &b){
return a.x*b.x+a.y*b.y;
}
long double xmult(Point p0,Point p1,Point p2) {///三点构成的两向量的叉积,p0是交点
return cross((p1-p0),(p2-p0));
}
///dot(p1-p0).(p2-p0)
long double dmult(Point p0,Point p1,Point p2){
return (p1.x-p0.x)*(p2.x-p0.x)+(p1.y-p0.y)*(p2.y-p0.y);
}
long double dis (Point a, Point b) {///两个点的距离
Point p = b-a; return p.len ();
}
///************直线 线段
struct Line {
Point s, e;///直线的两个点
double k;///极角
Line () {}
Line (Point _s, Point _e) {
s = _s, e = _e;
k = atan2 (e.y - s.y,e.x - s.x);
}
double length () {///求线段长度
return dis (s, e);
}
};
///点和直线的关系
int relation (Point p, Line l) {
///1:在左侧 2:在右侧 3:在直线上
int c = dcmp (cross (p-l.s, l.e-l.s));
if (c < 0) return 1;
else if (c > 0) return 2;
else return 3;
}
///判断点在线段上
bool point_on_seg (Point p, Line l) {
return dcmp (cross (p-l.s, l.e-l.s)) == 0 &&
dcmp (dot (p-l.s, p-l.e) <= 0);
///如果忽略端点交点改成小于号就好了
}
///判断点在射线上
bool point_on_halfline (Point p, Line l) {
int id = relation (p, l);
if (id != 3) return 0;
return dcmp (dot (p-l.s, l.e-l.s)) >= 0;
}
double point_to_line (Point p, Line a) {///点到直线的距离
return fabs (cross (p-a.s, a.e-a.s) / a.length ());
}
Point projection (Point p, Line a) {///点在直线上的投影
return a.s + (((a.e-a.s) * dot (a.e-a.s, p-a.s)) / (a.e-a.s).len2() );
}
Point symmetry (Point p, Line a) {///点关于直线的对称点
Point q = projection (p, a);
return Point (2*q.x-p.x, 2*q.y-p.y);
}
///***************圆
struct Circle {
///圆心 半径
Point p;
double r;
Circle () {}
Circle (Point _p, double _r) : p(_p), r(_r) {}
};
///直线和圆的关系
int relation (Line a, Circle b) {///直线和圆的交点
///0:相离 1:相切 2:相交
double p = point_to_line (b.p, a);
if (dcmp (p-b.r) == 0) return 1;
return (dcmp (p-b.r) < 0 ? 2 : 0);
}
int line_circle_intersection (Line v, Circle u, Point &p1, Point &p2) { ///返回交点个数 交点保存在引用中
if (!relation (v, u)) return 0;
Point a = projection (u.p, v);
double d = point_to_line (u.p, v);
d = sqrt (u.r*u.r - d*d);
if (dcmp (d) == 0) {
p1 = a, p2 = a;
return 1;
}
p1 = a + (v.e-v.s).change_len (d);
p2 = a - (v.e-v.s).change_len (d);
return 2;
}
Circle c;
long double vx,vy;
Point a,b;
void solve()
{
Point aa(a.x+vx,a.y+vy);
Line Start(a,aa);
Point jiao1,jiao2;
int num=line_circle_intersection(Start,c,jiao1,jiao2);
if(num<2)
{
if(dmult(a,aa,b)>eps&&fabs(xmult(a,aa,b))<eps)cout<<"Yes"<<endl;
else cout<<"No"<<endl;
}
else
{
Point jiao;
if(dis(a,jiao1)>dis(a,jiao2))
jiao=jiao2;
else
jiao=jiao1;
if(fabs(xmult(jiao,a,b))<eps&&dmult(jiao,a,b)>eps){cout<<"Yes"<<endl;return;}
Line ojiao(c.p,jiao);
Point ap=symmetry(a,ojiao);
if(dmult(jiao,ap,b)>eps&&fabs(xmult(jiao,ap,b))<eps)cout<<"Yes"<<endl;
else if(dmult(jiao,a,b)>eps&&fabs(xmult(jiao,a,b))<eps&&dis(a,jiao)>dis(a,b))cout<<"Yes"<<endl;
else cout<<"No"<<endl;
}
}
int main ()
{
int t;
scanf("%d",&t);
for(int cas=1;cas<=t;cas++)
{
cin>>c.p.x>>c.p.y>>c.r;
cin>>a.x>>a.y>>vx>>vy;
cin>>b.x>>b.y;
printf("Case #%d: ",cas);
solve();
}
return 0;
}
本文介绍了一种算法,用于判断在一个无限光滑平面上,一个小球在特定初始速度及方向下,是否会经过指定位置。该球可在碰撞固定圆柱体后以无能量损失的方式反弹。文章详细展示了输入输出格式,并提供了完整的C++代码实现。
&spm=1001.2101.3001.5002&articleId=73614011&d=1&t=3&u=bf1736aeb91d48b49ed54b80c4ae4787)
417

被折叠的 条评论
为什么被折叠?



