• poj 1263 Reflections (Simple Geometry)


    1263 -- Reflections

      简单计算几何。题目给出射线以及若干个不相交的圆,求出射线会在哪些圆上反弹,依次写出反弹球的编号。

    代码如下:

      1 #include <cstdio>
      2 #include <cstring>
      3 #include <iostream>
      4 #include <algorithm>
      5 #include <cmath>
      6 #include <vector>
      7 
      8 using namespace std;
      9 
     10 const double EPS = 1e-10;
     11 template<class T> T sqr(T x) { return x * x;}
     12 inline int sgn(double x) { return (x > EPS) - (x < -EPS);}
     13 struct Point {
     14     double x, y;
     15     Point() {}
     16     Point(double x, double y) : x(x), y(y) {}
     17     bool operator < (Point a) const { return sgn(x - a.x) < 0 || sgn(x - a.x) == 0 && y < a.y;}
     18     bool operator == (Point a) const { return sgn(x - a.x) == 0 && sgn(y - a.y) == 0;}
     19     Point operator + (Point a) { return Point(x + a.x, y + a.y);}
     20     Point operator - (Point a) { return Point(x - a.x, y - a.y);}
     21     Point operator * (double p) { return Point(x * p, y * p);}
     22     Point operator / (double p) { return Point(x / p, y / p);}
     23 } ;
     24 typedef Point Vec;
     25 
     26 inline double cross(Vec a, Vec b) { return a.x * b.y - a.y * b.x;}
     27 inline double cross(Point o, Point a, Point b) { return cross(a - o, b - o);}
     28 inline double dot(Vec a, Vec b) { return a.x * b.x + a.y * b.y;}
     29 inline double dot(Point o, Point a, Point b) { return dot(a - o, b - o);}
     30 inline double veclen(Vec x) { return sqrt(dot(x, x));}
     31 inline Vec normal(Vec x) { return Vec(-x.y, x.x) / veclen(x);}
     32 
     33 struct Line {
     34     Point s, t;
     35     Line() {}
     36     Line(Point s, Point t) : s(s), t(t) {}
     37     Vec vec() { return t - s;}
     38     Point pt(double x) { return s + vec() * x;}
     39     Line move(double x) {
     40         Vec nor = normal(vec());
     41         return Line(s + nor * x, t + nor * x);
     42     }
     43 } ;
     44 
     45 inline Point llint(Point P, Vec v, Point Q, Vec w) { return P + v * (cross(w, P - Q) / cross(v, w));}
     46 inline Point llint(Line a, Line b) { return llint(a.s, a.vec(), b.s, b.vec());}
     47 
     48 struct Circle {
     49     Point c;
     50     double r;
     51     Circle() {}
     52     Circle(Point c, double r) : c(c), r(r) {}
     53 } ;
     54 
     55 void lcint(Line L, Circle C, vector<Point> &sol) {
     56     Point ip = llint(L, Line(C.c, C.c + normal(L.vec())));
     57     double dis = veclen(ip - C.c);
     58     if (sgn(dis - C.r) >= 0) return ;
     59     Vec u = L.vec() / veclen(L.vec());
     60     double d = sqrt(sqr(C.r) - sqr(dis));
     61     sol.push_back(ip + u * d);
     62     sol.push_back(ip - u * d);
     63 }
     64 
     65 Point reflect(Point x, Line L) {
     66     Vec nor = normal(L.vec());
     67     Point ip = llint(L, Line(x, x + nor));
     68     return ip + ip - x;
     69 }
     70 
     71 vector<Circle> rec;
     72 Point src;
     73 Vec dir;
     74 
     75 const double FINF = 1e100;
     76 inline bool onCircle(Point p, Circle c) { return sgn(veclen(p - c.c) - c.r) == 0;}
     77 
     78 void work() {
     79     int cnt = 0, sz = rec.size();
     80     vector<Point> tmp;
     81     Point ip;
     82     while (true) {
     83         tmp.clear();
     84         double d = FINF;
     85         for (int i = 0; i < sz; i++) lcint(Line(src, src + dir), rec[i], tmp);
     86         for (int i = 0, sz = tmp.size(); i < sz; i++) {
     87             double t = (tmp[i].x - src.x) / dir.x;
     88             if (t > EPS) d = min(d, t);
     89         }
     90         if (sgn(d - FINF) >= 0) break;
     91         cnt++;
     92         if (cnt > 10) break;
     93         ip = src + dir * d;
     94         int mk = -1;
     95         for (int i = 0; i < sz; i++) if (onCircle(ip, rec[i])) { mk = i; break;}
     96         if (mk == -1) { puts("shit!!"); while (1) ;}
     97         printf("%d ", mk + 1);
     98         dir = reflect(src, Line(ip, rec[mk].c)) - ip;
     99         src = ip;
    100     }
    101     if (cnt > 10) puts("...");
    102     else puts("inf");
    103 }
    104 
    105 int main() {
    106 //    freopen("in", "r", stdin);
    107     int cas = 1, n;
    108     double x, y, r;
    109     while (cin >> n && n) {
    110         rec.clear();
    111         while (n--) {
    112             cin >> x >> y >> r;
    113             rec.push_back(Circle(Point(x, y), r));
    114         }
    115         cin >> src.x >> src.y;
    116         cin >> dir.x >> dir.y;
    117         dir = dir / veclen(dir);
    118         printf("Scene %d
    ", cas++);
    119         work();
    120         puts("");
    121     }
    122     return 0;
    123 }
    View Code

      速度好慢,整整写了一个小时。对几何模板还是不算非常熟悉,虽然已经能够灵活写出部分基础函数了,但是速度还真是一个大问题。最后结果,因为手多血多个换行PE了一次,然后就AC了~

    ——written by Lyon

  • 相关阅读:
    定时清理日志的shell脚本
    图解 Elestricsearch 写入流程
    消息队列产生严重消息堆积怎么处理?
    消息队列如何确保消息的有序性?
    架构模式 CQRS
    消息队列把消息弄丢了怎么办?
    3 个主流 Java 微服务框架
    RabbitMQ、Kafka、RocketMQ 是如何实现高可用的?
    Kafka 不再需要 ZooKeeper
    微服务设计原则
  • 原文地址:https://www.cnblogs.com/LyonLys/p/poj_1263_Lyon.html
Copyright © 2020-2023  润新知