hdu 5572 An Easy Physics Problem



链接:戳这里


An Easy Physics Problem


Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)
Total Submission(s): 697    Accepted Submission(s): 120


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

Source
2015ACM/ICPC亚洲区上海站-重现赛(感谢华东理工)


题意:给出一个圆C,一根射线A+V,一个点D,  问射线是否可以经过D点,如果碰到圆的换射线会反射,懂物理就知道了

题目给出射线的向量一定存在。且 A,D不会重合  A,D在圆外


思路:分两种情况讨论:

1 射线不经过圆  

2 射线经过圆

处理出射线与圆的交点,如果相切或者没有交点,情况1,如果有两个交点,情况2

那么我们求出射线与圆的交点

然后处理情况1(比较简单就不说了)。

情况2:首先求出与圆相交的两个点哪个是射线一开始交的点I,其实自己写直线与圆交的时候就可以推出来了

然后证明D点是在A->I线段上还是在I->D线段上,这里处理的方式有很多

但是我很奇怪啊 ,我不知道是不是精度问题还是思路问题,我判断I->A  I->D两个向量的夹角是否相等来证明就是WA

后来我改了思路就A了   很想要数据啊


代码:

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<string>
#include<vector>
#include <ctime>
#include<queue>
#include<set>
#include<map>
#include<stack>
#include<cmath>
#include<iomanip> /// setprecision()
#define mst(ss,b) memset((ss),(b),sizeof(ss))
#define MAX 1000100
///#pragma comment(linker, "/STACK:102400000,102400000")
typedef long long ll;
#define INF (1ll<<60)-1
using namespace std;
struct point {
    long double x,y;
    point(long double x=0,long double y=0):x(x),y(y) {}
};
const long double eps=1e-8;
const long double pi=acos(-1.0);
const long double maxn=1e20;
typedef point vec;
vec operator -(point a,point b) {
    return vec(a.x-b.x,a.y-b.y);
}
vec operator +(point a,point b) {
    return vec(a.x+b.x,a.y+b.y);
}
vec operator *(point a,long double t) {
    return vec(a.x*t,a.y*t);
}
vec operator /(point a,long double t) {
    return vec(a.x/t,a.y/t);
}
bool operator == (const point &a,const point &b) {
    if(fabs(a.x-b.x)<=eps && fabs(a.y-b.y)<=eps)
        return true;
    return false;
}
int dcmp(long double x) {
    if(fabs(x)<eps) return 0;
    return x<0?-1:1;
}
long double cross(vec a,vec b) {///叉积
    return a.x*b.y-a.y*b.x;
}
long double dot(vec a,vec b) {///点积
    return a.x*b.x+a.y*b.y;
}
long double lentgh(vec a) { ///向量长度
    return sqrt(dot(a,a));
}
struct line {
    point p;
    vec v;
    long double ang;
    line() {}
    line(point p,vec v):p(p),v(v) {
        ang=atan2(v.y,v.x);
    }
    point po(long double t) {
        return p+v*t;
    }
    bool operator < (const line &l) const {
        return ang<l.ang;
    }
};
struct circle {
    point c;
    long double r;
    circle() {}
    circle(point c,long double r):c(c),r(r) {}
    point po(long double a) {
        return point(c.x+cos(a)*r,c.y+sin(a)*r);
    }
} ;
int getlinecircleintersection(line L,circle C,long double &t1,long double &t2) {
    long double a=L.v.x;
    long double b=L.p.x-C.c.x;
    long double c=L.v.y;
    long double d=L.p.y-C.c.y;
    long double e=a*a+c*c;
    long double f=2*(a*b+c*d);
    long double g=b*b+d*d-C.r*C.r;
    long double delta=f*f-4*e*g;///判别式
    if(dcmp(delta)<0) return 0; ///相离
    if(dcmp(delta)==0) { ///相切
        t1=t2=-f/(2*e);
        return 1;
    }
    t1=(-f-sqrt(delta))/(2*e);
    t2=(-f+sqrt(delta))/(2*e);
    return 2;
}
bool onseg(point a,vec v,point b) {
    return dcmp(cross(v,b-a))==0;
    /*点在线段上 不包含端点(<=0)*/
}
bool onseg1(point p,point a1,point a2) {
    return dcmp(dot(a1-p,a2-p))<0;
    /*点在线段上 不包含端点(<=0)*/
}
double distancetoseg(point p,point a,point b){
    if(a==b) return lentgh(p-a);
    vec v1=b-a;
    vec v2=p-a;
    vec v3=p-b;
    if(dcmp(dot(v1,v2))<0)
        return lentgh(v2);
    else if(dcmp(dot(v1,v3))>0)
        return lentgh(v3);
    else
        return fabs(cross(v1,v2))/lentgh(v1);
    /*点到线段的距离*/
}
long double vec_angle(vec a,vec b) { ///两向量夹角
    return acos(dot(a,b)/lentgh(a)/lentgh(b));
}
long double getPos(vec v,vec t){
    if(dcmp(v.x)==0) return t.y/v.y;
    return t.x/v.x;
}
vec getnormal(vec a){
    return vec(-a.y,a.x);
}
bool getIntersection (point p, vec v, point q, vec w, point& o) {
    if (dcmp(cross(v, w)) == 0) return false;
    vec u = p - q;
    long double k = cross(w, u) / cross(v, w);
    o = p + v * k;
    return true;
}
circle C;
point A,D,M;  /// A B 不重合
vec V; /// V.x!=0 || V.y!=0
bool judge(){
    long double t1,t2,hint=maxn;
    line L=line(point(A),vec(V));
    int k=getlinecircleintersection(L,C,t1,t2);
    if(k>1 && dcmp(t1)>=0) hint=t1;
    else if(k>1 && dcmp(t2)>=0) hint=t2;
    ///cout<<setprecision(10)<<hint<<endl;
    if(onseg(A,V,D)){
        long double t=getPos(V,D-A);
        if(dcmp(t)>=0 && t<hint) return true;
    }
    if(dcmp(hint-maxn)<0){
        point I=A+V*hint,T;
        vec H=getnormal(C.c-I);
        getIntersection(I,H,D,C.c-I,T);
        D=T*2-D;
        if(onseg(A,V,D)){
            long double t=getPos(V,D-A);
            if(dcmp(t)>=0) return true;
        }
    }
    return false;
}
int main(){
    int T;
    scanf("%d",&T);
    for(int cas=1;cas<=T;cas++){
        cin>>C.c.x>>C.c.y>>C.r;
        cin>>A.x>>A.y;
        cin>>V.x>>V.y;
        cin>>D.x>>D.y;
        printf("Case #%d: %s\n",cas,judge()? "Yes" : "No");
    }
    return 0;
}
/*
10
1 0 1
4 0 -1 0
3 0
*/



你可能感兴趣的:(hdu 5572 An Easy Physics Problem)