Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Others)
Total Submission(s): 1151 Accepted Submission(s): 195
Problem Description
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 A, 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 B after some time.
Input
First line contains an integer T, which indicates the number of test cases.
Every test case contains three lines.
The first line contains three integers Ox, Oy and r, indicating the center of cylinder is (Ox,Oy) and its radius is r.
The second line contains four integers Ax, Ay, Vx and Vy, indicating the coordinate of A is (Ax,Ay) and the initial direction vector is (Vx,Vy).
The last line contains two integers Bx and By, indicating the coordinate of point B is (Bx,By).
⋅ 1 ≤ T ≤ 100.
⋅ |Ox|,|Oy|≤ 1000.
⋅ 1 ≤ r ≤ 100.
⋅ |Ax|,|Ay|,|Bx|,|By|≤ 1000.
⋅ |Vx|,|Vy|≤ 1000.
⋅ Vx≠0 or Vy≠0.
⋅ both A and B are outside of the cylinder and they are not at same position.
Output
For every test case, you should output “Case #x: y”, where x indicates the case number and counts from 1. y is “Yes” if the ball will pass point B after some time, otherwise y is “No”.
Sample Input
2
0 0 1
2 2 0 1
-1 -1
0 0 1
-1 2 1 -1
1 2
Sample Output
Case #1: No
Case #2: Yes
链接 http://acm.hdu.edu.cn/showproblem.php?pid=5572
给一个点a和它前进的方向,地图上还有一个圆柱,a撞到圆柱会反弹,问a会不会经过b点
撞上之后沿那一点的切线反弹,几何关系很明显
#include
#include
#include
using namespace std;
double eq=1e-6;
struct point
{
double x,y;
}o,a,b,v,d,t;
//a,b两点间距离的平方
double len_2(struct point a,struct point b)
{
return (a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y);
}
//a,b两点间距离
double len(struct point a,struct point b)
{
return sqrt(len_2(a,b));
}
//向量ab,ac的内积
double dot(struct point a,struct point b,struct point c)
{
return (b.x-a.x)*(c.x-a.x)+(b.y-a.y)+(c.y-a.y);
}
//向量ab叉乘ac的值
double cross(struct point a,struct point b,struct point c)
{
return (b.x-a.x)*(c.y-a.y)-(c.x-a.x)*(b.y-a.y);
}
//点p到直线Ax+By+C=0的距离的平方
double dis_2(struct point p,double A,double B,double C)
{
return (A*p.x+B*p.y+C)*(A*p.x+B*p.y+C)/(A*A+B*B);
}
//点p到直线Ax+By+C=0的距离
double dis(struct point p,double A,double B,double C)
{
return abs(A*p.x+B*p.y+C)/sqrt(A*A+B*B);
}
//已知向量ab与ac平行,判断是否同向
bool same_direction(struct point a,struct point b,struct point c)
{
b.x-=a.x;
b.y-=a.y;
c.x-=a.x;
c.y-=a.y;
if (abs(b.x-c.x)if ( abs(b.y-c.y)eq && c.y>eq) || (b.y<-eq && c.y<-eq) ) return true;
else return false;
}
else
{
if ( (b.x>eq && c.x>eq) || (b.x<-eq && c.x<-eq) ) return true;
else return false;
}
}
//直线Ax+By+C=0上距离点p最近的点
struct point closest_point(struct point p,double A,double B,double C)
{
struct point q;
q.x=(B*B*p.x-A*B*p.y-A*C)/(A*A+B*B);
q.y=(A*A*p.y-A*B*p.x-B*C)/(A*A+B*B);
return q;
}
//点p关于直线Ax+By+C=0的对称点
struct point symmetric_point(struct point p,double A,double B,double C)
{
struct point q;
q.x=2*closest_point(p,A,B,C).x-p.x;
q.y=2*closest_point(p,A,B,C).y-p.y;
return q;
}
//已知a,b,p共线,p是否在线段ab上
bool P_in_AB(struct point p,struct point a,struct point b)
{
if ( len_2(a,p)-len_2(a,b)return true;
else return false;
}
int main()
{
int T,ans;
scanf("%d",&T);
double r;
for (int kase=1;kase<=T;kase++)
{
ans=0;
scanf("%lf %lf %lf",&o.x,&o.y,&r);
scanf("%lf %lf %lf %lf",&a.x,&a.y,&v.x,&v.y);
scanf("%lf %lf",&b.x,&b.y);
double l=dis(o,v.y,-v.x,a.y*v.x-a.x*v.y);
double l_2=dis_2(o,v.y,-v.x,a.y*v.x-a.x*v.y);
t.x=a.x+v.x;
t.y=a.y+v.y;//t为直线上另一点
if ( l-r<-eq )
{
double ad=sqrt(len_2(a,o)-l_2)-sqrt(r*r-l_2);
double lv=sqrt(v.x*v.x+v.y*v.y);
d.x=a.x+v.x*ad/lv;
d.y=a.y+v.y*ad/lv;//交点
if (same_direction(a,t,d) || ( abs(a.x-d.x)abs(a.y-d.y)eq ) )//会撞上
{
//碰撞前
if (abs(cross(a,t,b))1;
b=symmetric_point(b,-(d.x-o.x),(o.y-d.y),d.x*(d.x-o.x)-d.y*(o.y-d.y));
}
}
if (abs(cross(a,t,b))//共线
{
if (same_direction(a,t,b)) ans=1;
}
if (ans) printf("Case #%d: Yes\n",kase);
else printf("Case #%d: No\n",kase);
}
return 0;
}
一上来写的姿势不太对,导致写了两个晚上。。不过也好。。自己手写了一些几何的板子出来。。。。