【poj 1263】球面反射
题目链接:https://vjudge.net/problem/POJ-1263
给你一个球的起始点和方向,球在圆面反射来反射去。
这题也是很少人过。基本上就是用到那几个常用函数:求点关于直线的对称点,求直线与圆的交点,向量旋转。。瞎搞搞。。。
1 /************************************************************************* 2 > File Name: poj1263.cpp 3 # File Name: poj1263.cpp 4 # Author : xiaobuxie 5 # QQ : 760427180 6 # Email:760427180@qq.com 7 # Created Time: 2019年10月26日 星期六 16时35分55秒 8 ************************************************************************/ 9 10 #include<iostream> 11 #include<cstdio> 12 #include<map> 13 #include<cmath> 14 #include<cstring> 15 #include<set> 16 #include<queue> 17 #include<vector> 18 #include<algorithm> 19 using namespace std; 20 typedef long long ll; 21 #define inf 0x3f3f3f3f 22 #define eps 1e-8 23 int sgn(double x){ 24 if(fabs(x) < eps) return 0; 25 if(x<0) return -1; 26 return 1; 27 } 28 const int N = 40; 29 const double pi = acos(-1.0); 30 struct Line{ 31 double a,b,c; 32 }; 33 struct Point{ 34 double x,y; 35 Point(){x=y=0;} 36 37 Point(double a,double b){x=a,y=b;} 38 39 Point operator - (const Point& b)const 40 {return Point(x-b.x,y-b.y);} 41 42 Point operator + (const Point& b)const 43 {return Point(x+b.x,y+b.y);} 44 45 Point operator * (const double& b)const 46 {return Point(x*b,y*b);} 47 48 Point rotate(const double& b)const 49 {return Point( x*cos(b) - y*sin(b) , x*sin(b) + y*cos(b) );} 50 51 Point corPoint(Line l)const{ 52 Point p2; 53 double d = l.a*l.a + l.b*l.b; 54 p2.x = ( (l.b*l.b - l.a*l.a)*x - 2 * l.a * l.b * y - 2*l.a*l.c) /d; 55 p2.y = ( (l.a*l.a - l.b*l.b)*y - 2 * l.a * l.b * x - 2*l.b*l.c) /d; 56 return p2; 57 } 58 59 double dot (const Point& b)const 60 {return x*b.x+y*b.y;} 61 62 double cross (const Point& b,const Point& c)const 63 {return (b.x - x)*(c.y - y) - (c.x - x)*(b.y - y);} 64 65 double ToPdis (const Point& b)const 66 {return sqrt( (x-b.x)*(x-b.x) + (y-b.y)*(y-b.y) );} 67 68 double ToLdis (Line l)const{ 69 return fabs(l.a * x + l.b * y + l.c) / sqrt(l.a*l.a + l.b*l.b); 70 } 71 72 bool OnLine (const Point& st,Point& ed)const 73 {return !sgn(cross(st,ed));} 74 75 bool OnSeg (const Point& st,Point& ed)const 76 {return OnLine(st,ed) && (*this - ed).dot(*this - st) < eps;} 77 }; 78 struct Circle{ 79 Point c; 80 double r; 81 }cir[N]; 82 83 Line twoPoLine(Point p1,Point p2){ 84 Line l; 85 l.a = p2.y - p1.y; 86 l.b = p1.x - p2.x; 87 l.c = p2.x * p1.y - p1.x * p2.y; 88 return l; 89 } 90 91 Point LineCross(Point a,Point b,Point c,Point d){ 92 double u = a.cross(b,c), v = b.cross(a,d); 93 return Point( (c.x*v + d.x*u)/(u+v) , (c.y*v + d.y*u)/(u+v) ); 94 } 95 96 double LineCrossCircle(Point a,Point b,Point o,double r,Point& p1,Point& p2){ 97 Point fp = LineCross(o,Point(o.x + a.y - b.y,o.y + b.x - a.x),a,b); 98 double atob = a.ToPdis(b); 99 double otol = o.ToPdis(fp); 100 double fptoe = sqrt( r*r - otol*otol ) / atob; 101 if( otol > r - eps) return otol; 102 p1 = fp + (a-b)*fptoe; 103 p2 = fp + (b-a)*fptoe; 104 return otol; 105 } 106 Point now,dir; 107 int n; 108 int find(){ 109 int id = -1; 110 Point tp; 111 for(int i = 1;i<=n;++i){ 112 Point p1,p2; 113 double dis = LineCrossCircle(now,dir,cir[i].c,cir[i].r,p1,p2); 114 if(dis - cir[i].r > -eps) continue; 115 if(sgn((dir - now).dot(p1 - now)) < 0) continue; 116 //cerr<<'p'<<p1.x<<' '<<p1.y<<endl; 117 //cerr<<i<<'a'<<now.cross(p1,dir)<<' '<<now.x<<' '<<now.y<<' '<<dir.x<<' '<<dir.y<<endl; 118 if( id == -1 || p1.ToPdis(now) < tp.ToPdis(now) ){ 119 tp = p1; 120 id = i; 121 } 122 if( id == -1 || p2.ToPdis(now) < tp.ToPdis(now) ){ 123 tp = p2; 124 id = i; 125 } 126 } 127 if(id == -1) return id; 128 Point tem = cir[id].c - tp; 129 tem = tem.rotate(pi/2.0); 130 tem = tem + tp; 131 Line l = twoPoLine(tem,tp); 132 Point tt = now.corPoint(l); 133 tem = tp - tt; 134 now = tp; 135 dir = tem + now; 136 return id; 137 } 138 int main(){ 139 int cas = 0; 140 while(~scanf("%d",&n) && n){ 141 printf("Scene %d\n",++cas); 142 for(int i = 1;i<=n;++i) scanf("%lf %lf %lf",&cir[i].c.x,&cir[i].c.y,&cir[i].r); 143 scanf("%lf %lf %lf %lf",&now.x,&now.y,&dir.x,&dir.y); 144 dir = now + dir; 145 int sum = 0; 146 int id=1; 147 while(1){ 148 int id = find(); 149 if(id == -1) break; 150 ++sum; 151 if(sum > 10) break; 152 printf("%d ",id); 153 } 154 if(sum <= 10) printf("inf\n\n"); 155 else printf("...\n\n"); 156 } 157 return 0;