zoukankan      html  css  js  c++  java
  • [LOJ 2039] 「SHOI2015」激光发生器

    [LOJ 2039] 「SHOI2015」激光发生器

    链接

    链接

    题解

    分为两个部分

    第一个是求直线之间的交点找到第一个触碰到的镜面

    第二个是求直线经过镜面反射之后的出射光线

    第一个很好做,第二个就是将入射光线旋转,注意旋转后在哪一面(可能到镜面背后去)

    代码

    // Copyright lzt
    #include<stdio.h>
    #include<cstring>
    #include<cstdlib>
    #include<algorithm>
    #include<vector>
    #include<map>
    #include<set>
    #include<cmath>
    #include<iostream>
    #include<queue>
    #include<string>
    #include<ctime>
    using namespace std;
    typedef long long ll;
    typedef pair<int, int> pii;
    typedef long double ld;
    typedef unsigned long long ull;
    typedef pair<long long, long long> pll;
    #define fi first
    #define se second
    #define pb push_back
    #define mp make_pair
    #define rep(i, j, k)  for (register int i = (int)(j); i <= (int)(k); i++)
    #define rrep(i, j, k) for (register int i = (int)(j); i >= (int)(k); i--)
    #define Debug(...) fprintf(stderr, __VA_ARGS__)
    
    inline ll read() {
      ll x = 0, f = 1;
      char ch = getchar();
      while (ch < '0' || ch > '9') {
      if (ch == '-') f = -1;
      ch = getchar();
      }
      while (ch <= '9' && ch >= '0') {
      x = 10 * x + ch - '0';
      ch = getchar();
      }
      return x * f;
    }
    
    const int maxn = 110;
    const double eps = 1e-8;
    const double pi = acos(-1);
    
    struct Point {
      double x, y;
      Point(double _x = 0, double _y = 0) {
        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};
      }
      Point operator * (const double &b) const {
        return (Point){x * b, y * b};
      }
    };
    typedef Point Vector;
    struct Line {
      Point x; Vector y;
      Line() {}
      Line(Point _x, Vector _y) {
        x = _x; y = _y;
      }
    };
    struct LLL {
      Point p1, p2;
      double a, b;
    } A[maxn];
    double Dot(const Vector &a, const Vector &b) {
      return a.x * b.x + a.y * b.y;
    }
    double Cross(const Vector &a, const Vector &b) {
      return a.x * b.y - a.y * b.x;
    }
    double Len(const Vector &a) {
      return sqrt(Dot(a, a));
    }
    int dcmp(double x) {
      return fabs(x) < eps ? 0 : (x > 0 ? 1 : -1);
    }
    Point intersect(const Line &a, const Line &b) {
      Vector v = a.x - b.x;
      double t = Cross(b.y, v) / Cross(a.y, b.y);
      return a.x + a.y * t;
    }
    double Angle(const Vector &a, const Vector &b) {
      return acos(Dot(a, b) / Len(a) / Len(b));
    }
    bool onseg(const Point &p, const Point &a, const Point &b) {
      return dcmp(Dot(a - p, b - p)) <= 0 && dcmp(Cross(a - p, a - p)) == 0;
    }
    Vector rotate(const Vector &a, double b) {
      return (Vector){a.x * cos(b) - a.y * sin(b), a.y * cos(b) + a.x * sin(b)};
    }
    double X, Y, dx, dy;
    int n;
    
    void work() {
      X = read(), Y = read(), dx = read(), dy = read();
      n = read();
      rep(i, 1, n) {
        A[i].p1.x = read(); A[i].p1.y = read();
        A[i].p2.x = read(); A[i].p2.y = read();
        A[i].a = read(), A[i].b = read();
      }
      Point nw = (Point){X, Y};
      Vector v = (Vector){dx, dy};
      rep(_, 1, 10) {
        int ind = 0; double nwdis = 1e9;
        rep(i, 1, n) {
          if (dcmp(Cross(A[i].p1 - A[i].p2, v)) == 0) continue;
          Point p = intersect(Line(A[i].p1, A[i].p2 - A[i].p1), Line(nw, v));
          if (onseg(p, A[i].p1, A[i].p2) && dcmp(Dot(v, p - nw)) > 0) {
            double dis = Len(p - nw);
            if (dis < nwdis) nwdis = dis, ind = i;
          }
        }
        if (!ind) {
          if (_ == 1) puts("NONE");
          break;
        }
        printf("%d ", ind);
        nw = intersect(Line(A[ind].p1, A[ind].p2 - A[ind].p1), Line(nw, v));
        if (dcmp(Dot(A[ind].p1 - A[ind].p2, v)) == 0) v = v * (-1);
        else {
          Vector nwv;
          if (dcmp(Dot(A[ind].p1 - A[ind].p2, v)) > 0) nwv = A[ind].p1 - A[ind].p2;
          else nwv = A[ind].p2 - A[ind].p1;
          double alpha = pi / 2 - Angle(nwv, v);
          if (dcmp(Cross(nwv, v)) > 0) v = rotate(nwv, alpha * A[ind].a / A[ind].b - pi / 2);
          else v = rotate(nwv, pi / 2 - alpha * A[ind].a / A[ind].b);
        }
      }
    }
    
    int main() {
      #ifdef LZT
      freopen("in", "r", stdin);
      #endif
    
      work();
    
      #ifdef LZT
      Debug("My Time: %.3lfms
    ", (double)clock() / CLOCKS_PER_SEC);
      #endif
    }
    
  • 相关阅读:
    L1-009. N个数求和
    L1-008. 求整数段和
    L1-007. 念数字
    L1-006. 连续因子
    L1-005. 考试座位号
    L1-003. 个位数统计
    mtk preloader学习笔记
    android kernel启动学习笔记
    android MTK平台编译UBOOT学习笔记
    dota2输入法无候选框?
  • 原文地址:https://www.cnblogs.com/wawawa8/p/10703945.html
Copyright © 2011-2022 走看看