leoanjos

Hole in One

Jun 2nd, 2023
715
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 4.68 KB | None | 0 0
  1. #include <bits/stdc++.h>
  2.  
  3. using namespace std;
  4.  
  5. #define llong long long int
  6. #define ldouble long double
  7. #define Vector Point
  8.  
  9. const ldouble EPS = 1e-9;
  10.  
  11. int sign(ldouble x) {
  12.     return fabsl(x) < EPS ? 0 : (x < 0 ? -1 : 1);
  13. }
  14.  
  15. template<typename T>
  16. struct Point {
  17.     T x, y;
  18.  
  19.     Point(): x(0), y(0) {}
  20.     Point(T x, T y): x(x), y(y) {}
  21.  
  22.     Point<T> operator +(Vector<T> v) {
  23.         return Point<T>(x + v.x, y + v.y);
  24.     }
  25.  
  26.     Vector<T> operator -(Point<T> other) {
  27.         return Vector<T>(x - other.x, y - other.y);
  28.     }
  29.  
  30.     Vector<T> operator *(T k) {
  31.         return Vector<T>(k * x, k * y);
  32.     }
  33.  
  34.     T operator *(Vector<T> other) {
  35.         return x * other.x + y * other.y;
  36.     }
  37.  
  38.     T operator /(Vector<T> other) {
  39.         return x * other.y - other.x * y;
  40.     }
  41.  
  42.     bool operator <(const Point<T> &other) const {
  43.         if (!sign(x - other.x))
  44.             return sign(y - other.y) < 0;
  45.  
  46.         return sign(x - other.x < 0);
  47.     }
  48. };
  49.  
  50. template<typename T>
  51. struct Segment {
  52.     bool active;
  53.     Point<T> P, Q;
  54.  
  55.     Segment(): active(false), P(Point<T>()), Q(Point<T>()) {}
  56.     Segment(Point<T> P, Point<T> Q): active(true), P(P), Q(Q) {}
  57.  
  58.     // Line PQ contains point R
  59.     bool contains(Point<T> R) {
  60.         T lx = sign(P.x - Q.x) < 0 ? P.x : Q.x, rx = sign(P.x - Q.x) > 0 ? P.x : Q.x;
  61.         T ly = sign(P.y - Q.y) < 0 ? P.y : Q.y, ry = sign(P.y - Q.y) > 0 ? P.y : Q.y;
  62.         return sign(R.x - lx) >= 0 && sign(rx - R.x) >= 0 && sign(R.y - ly) >= 0 && sign(ry - R.y) >= 0;
  63.     }
  64. };
  65.  
  66. template<typename T>
  67. struct Line {
  68.     Point<T> P;
  69.     Vector<T> v;
  70.  
  71.     Line(Point<T> P, Point<T> Q) {
  72.         if (Q < P) swap(P, Q);
  73.         this->P = P;
  74.         v = Q - P;
  75.     }
  76.  
  77.     pair<Point<T>, bool> intersection(Line<T> other) {
  78.         T den = v / other.v;
  79.         if (!sign(den)) return make_pair(Point<T>(), false);
  80.  
  81.         T t = ((other.P - P) / other.v) / den;
  82.         return make_pair(P + v * t, true);
  83.     }
  84.  
  85.     bool contains(Point<T> Q) {
  86.         return !sign((Q - P) / v);
  87.     }
  88. };
  89.  
  90. template<typename T>
  91. ldouble abs(Vector<T> v) {
  92.     return sqrtl(v * v);
  93. }
  94.  
  95. template<typename T>
  96. Point<T> reflect(Point<T> P, Segment<T> s) {
  97.     if (!sign(s.P.x - s.Q.x)) P.x = 2 * s.P.x - P.x;
  98.     else P.y = 2 * s.P.y - P.y;
  99.  
  100.     return P;
  101. }
  102.  
  103. template<typename T>
  104. pair<int, Point<T>> intersection(Point<T> origin, Vector<T> direction, vector<Segment<T>> &segments) {
  105.     int id = -1;
  106.     Point<T> ans;
  107.  
  108.     Line<T> l(origin, origin + direction);
  109.     for (int i = 0; i < (int) segments.size(); i++)
  110.         if (segments[i].active) {
  111.             auto [P, has_intersection] = l.intersection(Line<T>(segments[i].P, segments[i].Q));
  112.             if (has_intersection && segments[i].contains(P)) {
  113.                 if (!sign(direction.x)) {
  114.                     assert(sign(direction.y));
  115.                     T k = (P.y - origin.y) / direction.y;
  116.                     if (sign(k) < 0) continue;
  117.                 } else {
  118.                     T k = (P.x - origin.x) / direction.x;
  119.                     if (sign(k) < 0) continue;
  120.                 }
  121.  
  122.                 if (id == -1 || sign(abs(P - origin) - abs(ans - origin)) < 0)
  123.                     id = i, ans = P;
  124.             }
  125.         }
  126.  
  127.     return make_pair(id, ans);
  128. }
  129.  
  130. template<typename T>
  131. void ray_tracing(vector<int> &hits, Point<T> origin, Vector<T> direction, vector<Segment<T>> segments) {
  132.     auto [hit, P] = intersection(origin, direction, segments);
  133.     if (hit == -1) return;
  134.  
  135.     hits.push_back(hit);
  136.     segments[hit].active = false;
  137.     ray_tracing(hits, P, reflect(origin + direction, segments[hit]) - P, segments);
  138. }
  139.  
  140. int main() {
  141.     ios_base::sync_with_stdio(false);
  142.     cin.tie(NULL);
  143.  
  144.     int n; cin >> n;
  145.  
  146.     int x, y;
  147.     cin >> x >> y;
  148.  
  149.     vector<Segment<ldouble>> walls(n);
  150.     for (int i = 0; i < n; i++) {
  151.         int x1, y1, x2, y2;
  152.         cin >> x1 >> y1 >> x2 >> y2;
  153.  
  154.         Point<ldouble> P(x1, y1), Q(x2, y2);
  155.         walls[i] = Segment(P, Q);
  156.     }
  157.  
  158.     int ans = -1;
  159.     for (int i = 0; i < (1 << n); i++) {
  160.         vector<int> chosen;
  161.         for (int j = 0; j < n; j++)
  162.             if (i & (1 << j))
  163.                 chosen.push_back(j);
  164.  
  165.         do {
  166.             Point<ldouble> target(x, y);
  167.             for (auto it = chosen.rbegin(); it != chosen.rend(); it++)
  168.                 target = reflect(target, walls[*it]);
  169.  
  170.             vector<int> hits;
  171.             ray_tracing(hits, Point<ldouble>(), target, walls);
  172.  
  173.             if (hits == chosen) ans = max(ans, (int) hits.size());
  174.         } while (next_permutation(chosen.begin(), chosen.end()));
  175.     }
  176.  
  177.     if (ans == -1) cout << "impossible\n";
  178.     else cout << ans << "\n";
  179. }
Advertisement
Add Comment
Please, Sign In to add comment