链接:戳这里
题意:给出一个圆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 */