bzoj 4595 激光发生器

bzoj 4595 激光发生器

  • 光线为射线,每次找到与当前光线相交且距离最近的镜子,然后旋转光线.
  • 直线,射线利用线上一点+方向向量的方式表示.旋转时,旋转中心作为线上一点不变,方向向量左乘旋转矩阵.
  • 即逆时针转过 \(\theta\) 角,方向向量 \((x,y)\) 变为 \((cos\theta \cdot x-sin\theta \cdot y,sin\theta\cdot x+cos\theta\cdot y)\).
  • 实现时特判较多,需注意细节.
#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define mp make_pair
#define pii pair<int,int>
inline int read()
{
    int x=0;
    bool pos=1;
    char ch=getchar();
    for(;!isdigit(ch);ch=getchar())
        if(ch=='-')
            pos=0;
    for(;isdigit(ch);ch=getchar())
        x=x*10+ch-'0';
    return pos?x:-x;
}
const int MAXN=110;
const double eps=1e-8;
int dcmp(double x)
{
    return fabs(x)<=eps?0:(x>0?1:-1);
}
struct v2{
    double x,y;
    v2(double x=0,double y=0):x(x),y(y) {}
    v2 operator + (const v2 &rhs) const
        {
            return v2(x+rhs.x,y+rhs.y);
        }
    v2 operator / (const double &rhs) const
        {
            return v2(x/rhs,y/rhs);
        }
    v2 operator - (const v2 &rhs) const
        {
            return v2(x-rhs.x,y-rhs.y);
        }
    double operator * (const v2 &rhs) const
        {
            return x*rhs.y-y*rhs.x;
        }
    double modulus()
        {
            return sqrt(x*x+y*y);
        }
};
#define point v2
#define vector v2
v2 rotate(v2 v,double rad)
{
    return v2(v.x*cos(rad)-v.y*sin(rad),v.x*sin(rad)+v.y*cos(rad));
}
v2 inter(point p,vector v,point q,vector w)
{
    v2 u=p-q;
    double t=(w*u)/(v*w);
    return p+v2(v.x*t,v.y*t);
}
double dot(v2 a,v2 b)
{
    return a.x*b.x+a.y*b.y;
}
bool onseg(point p,point a1,point a2)
{
    return dcmp((a1-p)*(a2-p))==0 && dcmp(dot(a1-p,a2-p))<0; 
}
double angle(v2 a,v2 b)
{
    return acos(fabs(dot(a,b)/a.modulus()/b.modulus()-eps));
}
struct mir{
    v2 p1,p2;
    double a,b;
}a[MAXN];
double x,y,dx,dy;
int n;
int main()
{
    int cnt=0;
    scanf("%lf%lf%lf%lf",&x,&y,&dx,&dy);
    n=read();
    for(int i=1;i<=n;++i)
        scanf("%lf%lf%lf%lf%lf%lf",&a[i].p1.x,&a[i].p1.y,&a[i].p2.x,&a[i].p2.y,&a[i].a,&a[i].b);
    point p(x,y);
    vector v(dx,dy);
    for(int T=1;T<=10;++T)
        {
            double mdis=1e100;
            int id=0;
            for(int i=1;i<=n;++i)
                {
                    if(dcmp((a[i].p1-a[i].p2)*v)!=0)
                        {
                            point t=inter(a[i].p1,a[i].p2-a[i].p1,p,v);
                            if(onseg(t,a[i].p1,a[i].p2) && dcmp(dot(v,t-p))>0)
                                {
                                    double dis=(p-t).modulus();
                                    if(dis<mdis)
                                        mdis=dis,id=i;
                                }
                        }
                }
            if(id==0)
                break;
            ++cnt;
            p=inter(a[id].p1,a[id].p2-a[id].p1,p,v);
            if(dcmp(dot(a[id].p1-a[id].p2,v)==0))
                v=v2(-v.x,-v.y);
            else
                {
                    vector t=a[id].p2-a[id].p1;
                    if(dcmp(dot(a[id].p1-a[id].p2,v)>0))
                        t=t/(-1);
                    double alpha=acos(-1)/2-angle(t,v);
                    int bt=dcmp(t*v);
                    v=rotate(t,bt*(alpha*a[id].a/a[id].b-acos(-1)/2));
                }
            printf("%d ",id);
        }
    if(!cnt)
        puts("NONE");
    return 0;
}

猜你喜欢

转载自www.cnblogs.com/jklover/p/10388852.html