zoukankan      html  css  js  c++  java
  • 【LOJ】#2039. 「SHOI2015」激光发生器

    题解

    我永远都写不对计算几何……

    首先找到反射的线段比较好找,扫一遍所有线段然后找交点在镜子上并且交点离起点最近的那条线段

    然后旋转的时候,有可能是顺时针,也有可能是逆时针,要找出法线,然后判断法线和光线的角度然后确定顺时针逆时针

    代码

    #include <bits/stdc++.h>
    #define enter putchar('
    ')
    #define space putchar(' ')
    #define pii pair<int,int>
    #define fi first
    #define se second
    #define MAXN 200005
    #define pb push_back
    #define eps 1e-8
    //#define ivorysi
    using namespace std;
    typedef long long int64;
    typedef double db;
    template<class T>
    void read(T &res) {
        res = 0;T f = 1;char c = getchar();
        while(c < '0' || c > '9') {
            if(c == '-') f = -1;
            c = getchar();
        }
        while(c >= '0' && c <= '9') {
            res = res * 10 + c - '0';
            c = getchar();
        }
        res *= f;
    }
    template<class T>
    void out(T x) {
        if(x < 0) {x = -x;putchar('-');}
        if(x >= 10) out(x / 10);
        putchar('0' + x % 10);
    }
    bool dcmp(db a,db b) {
        return fabs(a - b) < eps;
    }
    struct Point {
        db x,y;
        Point(){}
        Point(db _x,db _y) {
            x = _x;y = _y;
        }
        friend Point operator + (const Point &a,const Point &b) {
            return Point(a.x + b.x,a.y + b.y);
        }
        friend Point operator - (const Point &a,const Point &b) {
            return Point(a.x - b.x,a.y - b.y);
        }
        friend Point operator * (const Point &a,const db &d) {
            return Point(a.x * d,a.y * d);
        }
        friend Point operator / (const Point &a,const db &d) {
            return Point(a.x / d,a.y / d);
        }
        friend db operator * (const Point &a,const Point &b) {
            return a.x * b.y - a.y * b.x;
        }
        friend db dot(const Point &a,const Point &b) {
            return a.x * b.x + a.y * b.y;
        }
        db norm() {
            return sqrt(x * x + y * y);
        }
    };
    struct Seg {
        Point a,b;db theta;
        Seg(){}
        Seg(Point _a,Point _b,db _theta = 0.0) {
            a = _a;b = _b;theta = _theta;
        }
        friend Point Cross_Point(const Seg &s,const Seg &t) {
            db S1 = (s.a - t.a) * (t.b - t.a);
            db S2 = (s.b - t.b) * (t.a - t.b);
            return s.a + (s.b - s.a) * (S1 / (S1 + S2));
        }
        bool in_Seg(Point P) {
            db d = (a - P) * (b - P);
            if(!dcmp(d,0.0)) return false;
            return  dot((a - P),(b - P)) <= eps;
        }
    }S[105],L;
    const db PI = acos(-1.0);
    int N,ans[15],tot;
    void Init() {
        db sx,sy,tx,ty,theta,a,b;
        scanf("%lf%lf%lf%lf",&sx,&sy,&tx,&ty);
        L = Seg(Point(sx,sy),Point(sx + tx,sy + ty));
        read(N);
        for(int i = 1 ; i <= N ; ++i) {
            scanf("%lf%lf%lf%lf%lf%lf",&sx,&sy,&tx,&ty,&a,&b);
            theta = a / b;
            S[i] = Seg(Point(sx,sy),Point(tx,ty),theta);
        }
    }
    void Solve() {
        int cnt = 10;
        while(cnt--) {
            int id = -1;Point t;
            for(int i = 1 ; i <= N ; ++i) {
                if(i == ans[tot]) continue;
                Point p = Cross_Point(L,S[i]);
                if(S[i].in_Seg(p) && dot(L.b - L.a,p - L.a) >= -eps) {
                    if(id == -1) {id = i;t = p;}
                    else if((p - L.a).norm() < (t - L.a).norm()) {
                        id = i;t = p;
                    }
                }
            }
            if(id == -1) break;
            ans[++tot] = id;
            db d = dot(L.b - L.a,S[id].b - S[id].a);
            db alpha = acos(fabs(d) / ((L.b - L.a).norm() * (S[id].b - S[id].a).norm()));
            alpha = PI / 2 - alpha;
            alpha = (S[id].theta + 1) * alpha;
            L.b = L.a;L.a = t;
            Seg ver = Seg(t,t + Point(-(S[id].b - S[id].a).y,(S[id].b - S[id].a).x));
            if(dot(ver.b - ver.a,L.b - L.a) <= eps) {
                ver = Seg(t,t + Point((S[id].b - S[id].a).y,-(S[id].b - S[id].a).x));
            }
            Point tmp = L.b - t;
            if((ver.b - ver.a) * (L.b - L.a) >= -eps) alpha = -alpha;
            L.b = t + Point(tmp.x * cos(alpha) - tmp.y * sin(alpha),tmp.x * sin(alpha) + tmp.y * cos(alpha));
        }
        if(!tot) puts("NONE");
        else {
            for(int i = 1 ; i <= tot ; ++i) {
                out(ans[i]);space;
            }
            enter;
        }
    }
    int main() {
    #ifdef ivorysi
        freopen("f1.in","r",stdin);
    #endif
        Init();
        Solve();
        return 0;
    }
    
  • 相关阅读:
    jQuery+d3绘制流程图OK
    jQuery+d3绘制流程图OK
    史上最全的后端技术大全,你都了解哪些技术呢?
    史上最全的后端技术大全,你都了解哪些技术呢?
    R语言面板数据分析步骤及流程
    R语言面板数据分析步骤及流程
    SQL Server之深入理解STUFF
    1048:有一门课不及格的学生
    1048:有一门课不及格的学生
    1047:判断能否被3,5,7整除
  • 原文地址:https://www.cnblogs.com/ivorysi/p/9493825.html
Copyright © 2011-2022 走看看