激光发生器
题解
我讨厌数学!!!
计算几何,欺负笔者数学差。
好吧,此题貌似有点坑,总之笔者调了半天。
这么小的数据,一看就是模拟。
其实此题可以分为两大版块,一个部分是求交点,挺好写的,还要判断一下在不在线上。
第二个部分是重点,就是该如何反射。
我们可以先求出它与法线的夹角,再将它旋转,使它达到它反射后的方向。
求夹角的可以用向量求夹角的公式:
再将它旋转,将向量旋转b角度后的向量为:
之后,就只需一个一个求就行了。
蒟蒻的一些奇思妙想
巨佬请跳过这段。
这是笔者这位蒟蒻考试时想的一个奇怪的方法,不过还没实现出来。
我们很容易就可以求出当前的,而我们又有二倍角公式:
与半倍角公式:
那么我们是否可以倍增无限逼近与呢?
因为与是小于1000的,所以我们可以在的时间中将其求出,这样来算之后的结果也不会超时呀?
不过笔者太弱了,没打出来。
源码
#include<bits/stdc++.h>
using namespace std;
#define MAXN 1005
typedef long long LL;
typedef pair<int,int> pii;
typedef pair<double,double> pdd;
#define re register
#define gc() getchar()
template<typename _T>
void read(_T &x){
_T f=1;x=0;char s=gc();
while(s>'9'||s<'0'){if(s=='-')f=-1;s=gc();}
while(s>='0'&&s<='9'){x=(x<<3)+(x<<1)+(s^48);s=gc();}
x*=f;
}
template<class _T>
inline bool cmin(_T &a,const _T&b){
return a>b?a=b,1:0;
}
int n,bt;
const double eps=1e-6,Pi=acos(-1.0),Loli=Pi*0.5;
double abs(double x){return x<-eps?-x:x;}
int sgn(double x){return x<-eps?-1:x>eps;}
struct point{
double x,y;
point(){}
point(double X,double Y):x(X),y(Y){}
point operator +(const point &b)const{return point(x+b.x,y+b.y);}
point operator -(const point &b)const{return point(x-b.x,y-b.y);}
double operator *(const point &b)const{return x*b.y-y*b.x;}
double operator ^(const point &b)const{return x*b.x+y*b.y;}
point operator *(const double &b)const{return point(x*b,y*b);}
inline double norm(){return sqrt(x*x+y*y);}
friend double ang(point &a,point &b){return acos((a^b)/a.norm()/b.norm());}
inline point rot(const double &b){
double s=sin(b),c=cos(b);
return point(x*c-y*s,x*s+y*c);
}
}p,v,c;
struct line{
point p,v;
line(){}
line(point a,point b){p=a;v=b-a;}
friend point cross(const line &a,const line &b){return a.p+a.v*(b.v*(b.p-a.p)/(b.v*a.v));}
bool onit(const point &b){return !sgn((b-p)*v)&&sgn((b-p)^(b-(p+v)))<0;}
}l[MAXN];
double reflect[MAXN],bet;
signed main(){
scanf("%lf %lf %lf %lf %d",&p.x,&p.y,&v.x,&v.y,&n);
for(int i=1;i<=n;i++){
double x,y,xx,yy,a,b;
scanf("%lf %lf %lf %lf %lf %lf",&x,&y,&xx,&yy,&a,&b);
l[i]=line(point(x,y),point(xx,yy));reflect[i]=a/b;
}
bool flag=false;
for(int t=1;t<=10;t++){
double minn=1e18;int id=0;
for(int i=1;i<=n;i++)
if(sgn(v*l[i].v)){
c=cross(line(p,p+v),l[i]);
if(l[i].onit(c)&&sgn(v^(c-p))>0&&cmin(minn,(c-p).norm()))
id=i;
}
if(!id)break;
p=cross(line(p,p+v),l[id]);
if(!sgn(v^l[id].v))v=v*-1;
else{
c=l[id].v;
if(sgn(c^v)<0)c=c*-1;
bet=Loli-ang(v,c),bt=sgn(c*v);
v=c.rot(bt*(bet*reflect[id]-Loli));
}
flag=true;printf("%d ",id);
}
if(!flag)puts("NONE");
return 0;
}