hdu3712 Detector Placement

题意:给一束激光,一个三棱柱,三棱柱会折射光,问这束激光最终是否会和y = 0相交;

分析:模拟题,为了方便处理折射角,事先求出每条边的向内和向外的法向量;

findpoint : 找第一交点

step1:  判断激光是否和三角形有规范相交;

step2: 第一次折射;

step3:第二次折射,可能无法折射;

  1 #include<cstdio>
  2 #include<cstring>
  3 #include<cstdlib>
  4 #include<iostream>
  5 #include<algorithm>
  6 #include<cmath>
  7 #include<vector>
  8 using namespace std;
  9 const int N = 100+10;
 10 const double eps = 1e-8;
 11 const double pi = acos(-1.0);
 12 inline int dcmp(double x) {
 13     return x < -eps ? -1 : x > eps;
 14 }
 15 inline double sqr(double x) {
 16     return x * x;
 17 }
 18 
 19 struct Point{
 20     double x,y;
 21     Point(){}
 22     Point(double _x,double _y):x(_x),y(_y){}
 23     bool operator == (const Point &p) const{
 24         return dcmp(x - p.x) == 0 && dcmp(y - p.y) == 0;
 25     }
 26     Point operator + (const Point &p) const{
 27         return Point(x + p.x, y + p.y);
 28     }
 29     Point operator - (const Point &p) const{
 30         return Point (x - p.x, y - p.y);
 31     }
 32     Point operator * (const double &k) const{
 33         return Point (x * k, y * k);
 34     }
 35     Point operator / (const double &k) const{
 36         return Point (x / k, y / k);
 37     }
 38     double operator * (const Point &p) const{
 39         return x * p.y - y * p.x;
 40     }
 41     double operator / (const Point &p) const{
 42         return x * p.x + y * p.y;
 43     }
 44     double len2() {
 45         return x * x + y * y;
 46     }
 47     double len() {
 48         return sqrt(len2());
 49     }
 50     Point scale(const double &k) {
 51         return dcmp( len() ) ? (*this) * (k / len()) : (*this);
 52     }
 53     Point turnLeft() {
 54         return Point(-y,x);
 55     }
 56     Point turnRight(){
 57         return Point(y,-x);
 58     }
 59     double Distance(const Point &p) {
 60         return sqrt(sqr(x - p.x) + sqr(y - p.y));
 61     }
 62     Point rotate(const Point &p,double angle, double k = 1) {
 63         Point vec = (*this) - p;
 64         double c = cos(angle * k)  , s =sin(angle * k) ;
 65         return p + Point(vec.x * c - vec.y * s, vec.x * s + vec.y * c);
 66     }
 67     void input(){
 68         scanf("%lf%lf",&x,&y);
 69     }
 70     void ot() {
 71         printf("%.3lf %.3lf\n",x,y);
 72     }
 73 };
 74 double Angle(Point a,Point b) {
 75     return (a/b) / a.len() / b.len();
 76 }
 77 struct Line{
 78     Point a,b;
 79     Line(){}
 80     Line(Point a,Point b):a(a),b(b){}
 81     double operator * (const Point &p) const{
 82         return (b - a) * (p - a);
 83     }
 84     double operator / (const Point &p) const{
 85         return (p - a) / (p - b);
 86     }
 87     bool IsPointOnSeg(const Point &p) {
 88         return dcmp( (a - p) * (b - p) ) == 0 && dcmp( (p - a) / (p - b) ) <= 0;
 89     }
 90     int LineCrossSeg(const Line &v) {//2jiao, 1 dian ,0 wu
 91         int d1 = dcmp( (*this) * v.a), d2 = dcmp((*this) * v.b);
 92         if ((d1 ^ d2) == -2) return 2;
 93         return (d1 == 0 || d2 == 0);
 94     }
 95     Point CrossPoint(const Line &v) {
 96         double s1 = v * a, s2 = v * b;
 97         return ( a * s2 - b * s1 ) / (s2 - s1);
 98     }
 99 };
100 Line li[3];
101 int d[3];
102 Point a[3],b[3],c[3];
103 Point st,en;
104 
105 double u;
106 int check(int i) {
107     if (dcmp( (li[i].b - li[i].a) * (a[d[i]] - li[i].a) ) > 0) {
108         return 1;
109     }
110     return 0;
111 }
112 void init(){
113     for (int i = 0; i < 3; i++) {
114         if (check(i)) {
115             b[i] = (li[i].b - li[i].a).turnLeft();
116             c[i] = (li[i].b - li[i].a).turnRight();
117         }else {
118             b[i] = (li[i].b - li[i].a).turnRight();
119             c[i] = (li[i].b - li[i].a).turnLeft();
120         }
121     }
122 }
123 int ond(Point a,Point b,Point p) {
124     if (dcmp((p - a) / (b - a)) >= 0) return 1;
125     return 0;
126 }
127 int step1() {
128     int fg = 0;
129     Line line = Line(st,en);
130     for (int i = 0; i < 3; i++) {
131         if (line.LineCrossSeg(li[i]) == 2) {
132             Point p = line.CrossPoint(li[i]);
133             if (ond(st,en,p)) fg = 1;
134         }
135     }
136     if (fg == 0) {
137 
138         Point p = line.CrossPoint(Line(Point(0,0),Point(1,0)));
139         if (ond(st,en,p)) printf("%.3lf\n",p.x+eps);
140         else printf("Error\n");
141         return 0;
142     }
143     return 1;
144 
145 }
146 void findPoint(Point &p,int &id) {
147     Line line = Line(st,en);
148     double dis = 1e50;
149     for (int i = 0; i < 3; i++) {
150         if (line.LineCrossSeg(li[i])) {
151             Point tp = line.CrossPoint(li[i]);
152             if (!ond(st,en,tp)) continue;
153             double tdis = tp.Distance(st);
154             if (tdis < dis && dcmp(tdis) != 0) {
155                 dis = tdis;
156                 p = tp;
157                 id = i;
158             }
159         }
160     }
161 }
162 void step2() {
163     Point p;
164     int id = -1;
165     findPoint(p,id);
166     Point vec = en - st;
167     double cs = Angle(vec,b[id]);
168     double sn1 = sqrt(1 - cs * cs);
169     double sn2 = sn1 / u;
170     double ag = asin(sn1) - asin(sn2);
171     if (dcmp(vec * b[id]) <= 0) {
172         vec = (p + vec).rotate(p,-ag);
173     }else vec = (p + vec).rotate(p,ag);
174     st = p; en = vec;
175 }
176 void step3() {
177     Point p;
178     int id = -1;
179     findPoint(p,id);
180     Point vec = en - st;
181     double cs = Angle(vec,c[id]);
182     double sn1 = sqrt(1 - cs * cs);
183     double sn2 = sn1 * u;
184     if (sn2 > 1) {
185         if (dcmp(p.y) == 0) printf("%.3lf\n",p.x+eps);
186         else printf("Error\n");
187         return;
188     }
189     double ag = asin(sn2) - asin(sn1);
190     if (dcmp(vec * c[id]) >= 0) {
191         vec = (p + vec).rotate(p,-ag);
192     }else vec = (p + vec).rotate(p,ag);
193     st = p; en = vec;
194     Point an = Line(st,en).CrossPoint(Line(Point(0,0),Point(1,0)));
195     if (ond(st,en,an)) {
196         printf("%.3lf\n",an.x+eps);
197     }else printf("Error\n");
198 }
199 void solve(){
200     init();
201     if (!step1()) return;
202     step2();
203     step3();
204 }
205 int main(){
206    // cout<<Line(Point(0,0),Point(1,0)).LineCrossSeg(Line(Point(0,0),Point(1,0)))<<endl;
207     int T; scanf("%d",&T);
208     while (T--) {
209         st.input(); en.input();
210         for (int i = 0; i < 3; i++) a[i].input();
211         li[0] = Line(a[0],a[1]); d[0] = 2;
212         li[1] = Line(a[1],a[2]); d[1] = 0;
213         li[2] = Line(a[2],a[0]); d[2] = 1;
214         scanf("%lf",&u);
215         solve();
216     }
217     return 0;
218 }
219 /*
220 3
221 0 10
222 0 20
223 -1 3 1 2 -1 1
224 1.325
225 0 10
226 0 0
227 -1 3 1 2 -1 1
228 1.325
229 
230 0 10 0 9
231 0 0 0 1 1 0
232 1.0
233 */
View Code

 

posted @ 2013-10-30 23:32  Rabbit_hair  阅读(391)  评论(0编辑  收藏  举报