BZOJ 4595 SHOI2015 激光发生器 射线,线段,偏转

题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=4595

 

题意概述:

  给出一条射线和N条线段,射线遇到线段会发生反射,令入射角alpha,出射角beta,则beta=alpha*phi_i(即对于每条线段phi是不同的),输出至多10条遇见的线段,没有发生相交的话输出NONE。

N<=100.

 

分析:

  实际上记得板子怎么打还是没什么问题的,问题就是我当时记不得了......

  还有一个事情,用余弦定理求两个向量夹角的时候记得-eps控制精度!

 

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cstring>
 4 #include<cstdlib>
 5 #include<algorithm>
 6 #include<cmath>
 7 #include<queue>
 8 #include<set>
 9 #include<map>
10 #include<vector>
11 #include<cctype>
12 using namespace std;
13 const int maxn=105;
14 const double eps=1e-8;
15 const double pi=acos(-1.0);
16 
17 int X,Y,dx,dy,N;
18 struct Point{
19     double x,y;
20     Point(){ }
21     Point(double xx,double yy){ x=xx,y=yy; }
22 }P[maxn]; int cnt=0;
23 typedef Point Vector;
24 struct Line{
25     Point p; Vector v;
26     Line(){    }
27     Line(Point pp,Vector vv){ p=pp,v=vv; }
28 };
29 struct data{
30     int a,b;
31     Point p1,p2;
32 }A[maxn];
33 Vector operator + (const Vector &a,const Vector &b){ return Vector(a.x+b.x,a.y+b.y); }
34 Vector operator - (const Vector &a,const Vector &b){ return Vector(a.x-b.x,a.y-b.y); }
35 Vector operator * (const Vector &a,const double &b){ return Vector(a.x*b,a.y*b); }
36 int dcmp(double x){ return fabs(x)<eps?0:(x>0?1:-1); }
37 double Dot(const Vector &a,const Vector &b){ return a.x*b.x+a.y*b.y; }
38 double Cross(const Vector &a,const Vector &b){ return a.x*b.y-a.y*b.x; }
39 double Length(const Vector &a){ return sqrt(a.x*a.x+a.y*a.y); }
40 double Angle(const Vector &a,const Vector &b){ return acos(fabs(Dot(a,b))/Length(a)/Length(b)-eps); }
41 Vector Rotate(const Vector &v,const double &rad){
42     return Vector(v.x*cos(rad)-v.y*sin(rad),v.y*cos(rad)+v.x*sin(rad));
43 }
44 Point GetLineIntersection(const Line &a,const Line &b){
45     Vector u=a.p-b.p;
46     double t=Cross(b.v,u)/Cross(a.v,b.v);
47     return a.p+a.v*t;
48 }
49 bool Onsegment(const Point &p,const Point &a,const Point &b){
50     return dcmp(Dot(a-p,b-p))<=0&&dcmp(Cross(a-p,a-p))==0;
51 }
52 
53 void data_in()
54 {
55     scanf("%d%d%d%d%d",&X,&Y,&dx,&dy,&N);
56     for(int i=1;i<=N;i++)
57         scanf("%lf%lf%lf%lf%d%d",&A[i].p1.x,&A[i].p1.y,&A[i].p2.x,&A[i].p2.y,&A[i].a,&A[i].b);
58 }
59 void work()
60 {
61     int t=1;
62     Point p=Point(X,Y),pp;
63     Vector v=Vector(dx,dy),vv;
64     while(t<=10){
65         double md=1e9,dis; int id=0;
66         for(int i=1;i<=N;i++){
67             if(dcmp(Cross(A[i].p1-A[i].p2,v))==0) continue;
68             pp=GetLineIntersection(Line(A[i].p1,A[i].p2-A[i].p1),Line(p,v));
69             if(Onsegment(pp,A[i].p1,A[i].p2)&&dcmp(Dot(v,pp-p))>0){
70                 dis=Length(p-pp);
71                 if(dis<md) md=dis,id=i;
72             }
73         }
74         if(!id) break;
75         p=GetLineIntersection(Line(A[id].p1,A[id].p2-A[id].p1),Line(p,v));
76         if(dcmp(Dot(A[id].p1-A[id].p2,v))==0) v=v*-1;
77         else{
78             if(dcmp(Dot(A[id].p1-A[id].p2,v))>0) vv=A[id].p1-A[id].p2;
79             else vv=A[id].p2-A[id].p1;
80             double alp=pi/2-Angle(vv,v);
81             if(dcmp(Cross(vv,v))>0) v=Rotate(vv,alp*A[id].a/A[id].b-pi/2);
82             else v=Rotate(vv,pi/2-alp*A[id].a/A[id].b);
83         }
84         printf("%d ",id);
85         t++;
86     }
87     if(t==1) printf("NONE\n");
88 }
89 int main()
90 {
91     data_in();
92     work();
93     return 0;
94 }
View Code

 

posted @ 2018-03-25 20:16  KKKorange  阅读(516)  评论(0编辑  收藏  举报