Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #include <bits/stdc++.h>
- using namespace std;
- #define llong long long int
- #define ldouble long double
- #define Vector Point
- const ldouble EPS = 1e-9;
- int sign(ldouble x) {
- return fabsl(x) < EPS ? 0 : (x < 0 ? -1 : 1);
- }
- template<typename T>
- struct Point {
- T x, y;
- Point(): x(0), y(0) {}
- Point(T x, T y): x(x), y(y) {}
- Point<T> operator +(Vector<T> v) {
- return Point<T>(x + v.x, y + v.y);
- }
- Vector<T> operator -(Point<T> other) {
- return Vector<T>(x - other.x, y - other.y);
- }
- Vector<T> operator *(T k) {
- return Vector<T>(k * x, k * y);
- }
- T operator *(Vector<T> other) {
- return x * other.x + y * other.y;
- }
- T operator /(Vector<T> other) {
- return x * other.y - other.x * y;
- }
- bool operator <(const Point<T> &other) const {
- if (!sign(x - other.x))
- return sign(y - other.y) < 0;
- return sign(x - other.x < 0);
- }
- };
- template<typename T>
- struct Segment {
- bool active;
- Point<T> P, Q;
- Segment(): active(false), P(Point<T>()), Q(Point<T>()) {}
- Segment(Point<T> P, Point<T> Q): active(true), P(P), Q(Q) {}
- // Line PQ contains point R
- bool contains(Point<T> R) {
- T lx = sign(P.x - Q.x) < 0 ? P.x : Q.x, rx = sign(P.x - Q.x) > 0 ? P.x : Q.x;
- T ly = sign(P.y - Q.y) < 0 ? P.y : Q.y, ry = sign(P.y - Q.y) > 0 ? P.y : Q.y;
- return sign(R.x - lx) >= 0 && sign(rx - R.x) >= 0 && sign(R.y - ly) >= 0 && sign(ry - R.y) >= 0;
- }
- };
- template<typename T>
- struct Line {
- Point<T> P;
- Vector<T> v;
- Line(Point<T> P, Point<T> Q) {
- if (Q < P) swap(P, Q);
- this->P = P;
- v = Q - P;
- }
- pair<Point<T>, bool> intersection(Line<T> other) {
- T den = v / other.v;
- if (!sign(den)) return make_pair(Point<T>(), false);
- T t = ((other.P - P) / other.v) / den;
- return make_pair(P + v * t, true);
- }
- bool contains(Point<T> Q) {
- return !sign((Q - P) / v);
- }
- };
- template<typename T>
- ldouble abs(Vector<T> v) {
- return sqrtl(v * v);
- }
- template<typename T>
- Point<T> reflect(Point<T> P, Segment<T> s) {
- if (!sign(s.P.x - s.Q.x)) P.x = 2 * s.P.x - P.x;
- else P.y = 2 * s.P.y - P.y;
- return P;
- }
- template<typename T>
- pair<int, Point<T>> intersection(Point<T> origin, Vector<T> direction, vector<Segment<T>> &segments) {
- int id = -1;
- Point<T> ans;
- Line<T> l(origin, origin + direction);
- for (int i = 0; i < (int) segments.size(); i++)
- if (segments[i].active) {
- auto [P, has_intersection] = l.intersection(Line<T>(segments[i].P, segments[i].Q));
- if (has_intersection && segments[i].contains(P)) {
- if (!sign(direction.x)) {
- assert(sign(direction.y));
- T k = (P.y - origin.y) / direction.y;
- if (sign(k) < 0) continue;
- } else {
- T k = (P.x - origin.x) / direction.x;
- if (sign(k) < 0) continue;
- }
- if (id == -1 || sign(abs(P - origin) - abs(ans - origin)) < 0)
- id = i, ans = P;
- }
- }
- return make_pair(id, ans);
- }
- template<typename T>
- void ray_tracing(vector<int> &hits, Point<T> origin, Vector<T> direction, vector<Segment<T>> segments) {
- auto [hit, P] = intersection(origin, direction, segments);
- if (hit == -1) return;
- hits.push_back(hit);
- segments[hit].active = false;
- ray_tracing(hits, P, reflect(origin + direction, segments[hit]) - P, segments);
- }
- int main() {
- ios_base::sync_with_stdio(false);
- cin.tie(NULL);
- int n; cin >> n;
- int x, y;
- cin >> x >> y;
- vector<Segment<ldouble>> walls(n);
- for (int i = 0; i < n; i++) {
- int x1, y1, x2, y2;
- cin >> x1 >> y1 >> x2 >> y2;
- Point<ldouble> P(x1, y1), Q(x2, y2);
- walls[i] = Segment(P, Q);
- }
- int ans = -1;
- for (int i = 0; i < (1 << n); i++) {
- vector<int> chosen;
- for (int j = 0; j < n; j++)
- if (i & (1 << j))
- chosen.push_back(j);
- do {
- Point<ldouble> target(x, y);
- for (auto it = chosen.rbegin(); it != chosen.rend(); it++)
- target = reflect(target, walls[*it]);
- vector<int> hits;
- ray_tracing(hits, Point<ldouble>(), target, walls);
- if (hits == chosen) ans = max(ans, (int) hits.size());
- } while (next_permutation(chosen.begin(), chosen.end()));
- }
- if (ans == -1) cout << "impossible\n";
- else cout << ans << "\n";
- }
Advertisement
Add Comment
Please, Sign In to add comment