Problem p01626 (C++) — buggy submission, verdict: Runtime Error

#include <bits/stdc++.h>
using namespace std;
typedef complex<double> P;
typedef complex<double> V;
typedef vector<P> vecP;
typedef pair<P, P> L;
typedef pair<P, P> S;

const double eps = 1e-5;
const double PI = acos(-1);
const double PI2 = PI * 2.0;

namespace std {
bool operator<(const P &a, const P &b) {
  return (a.real() != b.real() ? a.real() < b.real() : a.imag() < b.imag());
}
}; // namespace std

V normal(V a) {
  assert(abs(a) > 0);
  return a / abs(a);
}

double Sqrt(double x) {
  if (x < 0)
    return 0;
  else
    return sqrt(x);
}

P Vector(L a) { return a.second - a.first; }

bool eq(double a, double b) {
  double ep = max(eps, max(abs(a), abs(b)) * eps);
  return (-ep < a - b && a - b < ep);
}

bool eq(P a, P b) { return (eq(a.real(), b.real()) && eq(a.imag(), b.imag())); }

double dot(P a, P b) { return real(b * conj(a)); }

double cross(P a, P b) { return imag(b * conj(a)); }

double getArg(P a, P b) { return arg(b * conj(a)); }

double getTime(V a, V b) {
  assert(eq(cross(a, b), 0));
  return (dot(a, b) < 0 ? -1.0 : 1.0) * abs(b) / abs(a);
}

P project(P a, P b, P c) {
  b -= a, c -= a;
  return a + b * real(c / b);
}

P reflect(P a, P b, P c) {
  b -= a, c -= a;
  return a + b * conj(c / b);
}
P reflect(S s, P p) { return reflect(s.first, s.second, p); }

int ccw(P a, P b, P c) {
  P ab = b - a, ac = c - a;
  P k = ac * conj(ab);
  if (k.imag() > eps)
    return 1;
  if (k.imag() < -eps)
    return -1;
  if (k.real() < -eps)
    return 2;
  if (abs(ab) + eps < abs(ac))
    return -2;
  return 0;
}

bool isParallel(P a, P b) { return eq(0, cross(a, b)); }

bool isParallel(S a, S b) { return eq(0, cross(Vector(a), Vector(b))); }

bool onLP(L l, P p) {
  P a = l.first, b = l.second;
  return eq(0, cross(b - a, p - a));
}

bool onSP(S s, P p) {
  P a = s.first, b = s.second;
  return eq(abs(b - a), abs(a - p) + abs(b - p));
}

bool isCrossSS(S s0, S s1) {
  P a = s0.first, b = s0.second;
  P c = s1.first, d = s1.second;
  int f0 = ccw(a, b, c) * ccw(a, b, d);
  int f1 = ccw(c, d, a) * ccw(c, d, b);
  return (f0 <= 0 && f1 <= 0);
}

bool isCrossLS(L l, S s) {
  P a = l.first, b = l.second;
  P c = s.first, d = s.second;
  return (ccw(a, b, c) * ccw(a, b, d) <= 0);
}

double distLP(L l, P p) {
  P a = l.first, b = l.second;
  double res = cross(b - a, p - a) / abs(b - a);
  return abs(res);
}

double distSP(S s, P p) {
  P a = s.first, b = s.second;
  if (dot(b - a, p - a) < eps)
    return abs(p - a);
  if (dot(a - b, p - b) < eps)
    return abs(p - b);
  return distLP(s, p);
}

double distSS(S s0, S s1) {
  if (isCrossSS(s0, s1))
    return 0;
  double res0 = min(distSP(s0, s1.first), distSP(s0, s1.second));
  double res1 = min(distSP(s1, s0.first), distSP(s1, s0.second));
  return min(res0, res1);
}

P getCrossLL(L l0, L l1) {
  P a = l0.first, b = l0.second;
  P c = l1.first, d = l1.second;
  a -= d;
  b -= d;
  c -= d;
  return d + a + (b - a) * imag(a / c) / imag(a / c - b / c);
}

P getVector(const vecP &t, int id) {
  int n = t.size();
  return t[(id + 1) % n] - t[id % n];
}

void pr(P p, string str = "\\n") {
  printf("%.10f %.10f", p.real(), p.imag());
  cout << str;
}

int checkPolygonP(vecP &t, P p) {
  int n = t.size();
  double sum = 0;
  for (int i = 0; i < n; i++) {
    P a = t[i], b = t[(i + 1 == n ? 0 : i + 1)];
    if (ccw(a, b, p) == 0) {
      return 1;
    }
    sum += getArg(a - p, b - p);
  }
  if (abs(sum) < eps)
    return 0;
  return 2;
}

void checkPolygonS(vecP &t, S s, int &maxm, int &mini) {
  int n = t.size();

  typedef pair<double, int> Pair;

  vector<P> u;
  vector<Pair> v;
  for (int i = 0; i < n; i++) {
    P a = t[i], b = t[(i + 1 == n ? 0 : i + 1)];
    S base = S(a, b);
    if (isParallel(base, s))
      continue;
    if (!isCrossSS(base, s))
      continue;

    P target = getCrossLL(base, s);

    if (!onLP(s, target)) {
      cout << s.first << ' ' << s.second << endl;
      cout << base.first << ' ' << base.second << endl;
      cout << target << endl;
      continue;
    }

    Pair pair;
    pair.first = getTime(s.second - s.first, target - s.first);
    pair.second = u.size();
    u.push_back(target);
    v.push_back(pair);
  }

  v.push_back(Pair(0.0, u.size()));
  u.push_back(s.first);
  v.push_back(Pair(1.0, u.size()));
  u.push_back(s.second);
  sort(v.begin(), v.end());

  maxm = -1;
  mini = 3;
  for (int i = 0; i < (int)v.size(); i++) {
    int f = checkPolygonP(t, u[v[i].second]);
    maxm = max(maxm, f);
    mini = min(mini, f);
    if (i + 1 < (int)v.size()) {
      int h = checkPolygonP(t, (u[v[i].second] + u[v[i + 1].second]) * 0.5);
      maxm = max(maxm, h);
      mini = min(mini, h);
    }
  }
}

bool inPolygonS(vecP &t, S s) {
  int maxm, mini;
  checkPolygonS(t, s, maxm, mini);
  if (mini == 0)
    return false;
  return true;
}

bool outPolygonS(vecP &t, S s) {
  int maxm, mini;
  checkPolygonS(t, s, maxm, mini);
  if (maxm == 2)
    return false;
  return true;
}

void pr(P p) { printf("%.3f %.3f\\n", p.real(), p.imag()); }

////////////////

struct state {
  double cost;
  int pos;
  state(double x, int y) : cost(x), pos(y) {}
  bool operator<(const state &s) const { return cost > s.cost; }
};

P input() {
  double x, y;
  cin >> x >> y;
  return P(x, y);
}

S getS(vecP &t, int index) {
  int n = t.size();
  index %= n;
  return S(t[index], t[(index + 1) % n]);
}

double solve(vector<vecP> &a, P si, P ti, L line) {
  vecP A, B;
  for (int i = 0; i < (int)a.size(); i++) {
    if (checkPolygonP(a[i], si) > 0 && checkPolygonP(a[i], ti) > 0) {
      A = a[i];
    }
    if (checkPolygonP(a[i], reflect(line, si)) > 0 &&
        checkPolygonP(a[i], reflect(line, ti)) > 0) {
      B = a[i];
    }
  }
  if (A.empty() || B.empty())
    return -1;
  for (int i = 0; i < (int)B.size(); i++)
    B[i] = reflect(line, B[i]);
  vecP t;
  for (int i = 0; i < (int)A.size(); i++)
    t.push_back(A[i]);
  for (int i = 0; i < (int)B.size(); i++)
    t.push_back(B[i]);
  for (int i = 0; i < (int)A.size(); i++) {
    for (int j = 0; j < (int)B.size(); j++) {
      S fi = getS(A, i);
      S se = getS(B, j);
      if (!isParallel(fi, se) && isCrossSS(fi, se)) {
        t.push_back(getCrossLL(fi, se));
      }
    }
  }

  t.push_back(si);
  t.push_back(ti);
  sort(t.begin(), t.end());
  t.erase(unique(t.begin(), t.end()), t.end());

  vector<double> d(t.size(), 1e9);
  int sid = lower_bound(t.begin(), t.end(), si) - t.begin();
  int tid = lower_bound(t.begin(), t.end(), ti) - t.begin();

  d[sid] = 0;
  priority_queue<state> Q;
  Q.push(state(0, sid));
  while (!Q.empty()) {
    state s = Q.top();
    Q.pop();

    if (s.pos == tid)
      return s.cost;

    if (d[s.pos] < s.cost)
      continue;
    for (int to = 0; to < (int)t.size(); to++) {
      if (s.pos == to)
        continue;
      S path = S(t[s.pos], t[to]);
      if (!inPolygonS(A, path))
        continue;
      if (!inPolygonS(B, path))
        continue;
      double ncost = s.cost + abs(path.second - path.first);
      if (d[to] - eps > ncost) {
        d[to] = ncost;
        Q.push(state(ncost, to));
      }
    }
  }

  return -1;
}

int main() {
  int n;

  while (cin >> n && n) {
    //    cout<<n<<" ";
    vector<vecP> a;
    a.resize(n);
    for (int i = 0; i < n; i++) {
      int m;
      cin >> m;
      //      cout<<m<<" ";
      a[i].resize(m);
      for (int j = 0; j < m; j++) {
        a[i][j] = input();
      }
    }

    P si = input();
    P ti = input();

    L line;
    line.first = input();
    line.second = input();

    double ans = solve(a, si, ti, line);

    if (n == 2 && (int)a[0].size() == 50 && (int)a[1].size() == 4) {
      //      cout<<n<<' '<<a[0].size()<<' '<<a[1].size()<<endl;
      /*

      cout<<n<<endl;
      for(int i=0;i<n;i++){
        cout<<a[i].size()<<endl;
        for(int j=0;j<(int)a[i].size();j++){
          cout<<a[i][j].real()<<' '<<a[i][j].imag()<<endl;
        }
      }
        cout<<si.real()<<' '<<si.imag()<<endl;
        cout<<ti.real()<<' '<<ti.imag()<<endl;
        cout<< line.first.real()<<' '<<line.first.imag()<<endl;
        cout<< line.second.real()<<' '<<line.second.imag()<<endl;
      */
    }

    if (ans < 0) {
      printf("impossible\\n");
    } else {
      printf("%.10f\\n", ans);
    }
  }
  return 0;
}

Error: WA

Fixed submission:

#include <bits/stdc++.h>
using namespace std;
typedef complex<double> P;
typedef complex<double> V;
typedef vector<P> vecP;
typedef pair<P, P> L;
typedef pair<P, P> S;

const double eps = 1e-8;
const double PI = acos(-1);
const double PI2 = PI * 2.0;

namespace std {
bool operator<(const P &a, const P &b) {
  return (a.real() != b.real() ? a.real() < b.real() : a.imag() < b.imag());
}
}; // namespace std

V normal(V a) {
  assert(abs(a) > 0);
  return a / abs(a);
}

double Sqrt(double x) {
  if (x < 0)
    return 0;
  else
    return sqrt(x);
}

P Vector(L a) { return a.second - a.first; }

bool eq(double a, double b) {
  double ep = max(eps, max(abs(a), abs(b)) * eps);
  return (-ep < a - b && a - b < ep);
}

bool eq(P a, P b) { return (eq(a.real(), b.real()) && eq(a.imag(), b.imag())); }

double dot(P a, P b) { return real(b * conj(a)); }

double cross(P a, P b) { return imag(b * conj(a)); }

double getArg(P a, P b) { return arg(b * conj(a)); }

double getTime(V a, V b) {
  assert(eq(cross(a, b), 0));
  return (dot(a, b) < 0 ? -1.0 : 1.0) * abs(b) / abs(a);
}

P project(P a, P b, P c) {
  b -= a, c -= a;
  return a + b * real(c / b);
}

P reflect(P a, P b, P c) {
  b -= a, c -= a;
  return a + b * conj(c / b);
}
P reflect(S s, P p) { return reflect(s.first, s.second, p); }

int ccw(P a, P b, P c) {
  P ab = b - a, ac = c - a;
  P k = ac * conj(ab);
  if (k.imag() > eps)
    return 1;
  if (k.imag() < -eps)
    return -1;
  if (k.real() < -eps)
    return 2;
  if (abs(ab) + eps < abs(ac))
    return -2;
  return 0;
}

bool isParallel(P a, P b) { return eq(0, cross(a, b)); }

bool isParallel(S a, S b) { return eq(0, cross(Vector(a), Vector(b))); }

bool onLP(L l, P p) {
  P a = l.first, b = l.second;
  return eq(0, cross(b - a, p - a));
}

bool onSP(S s, P p) {
  P a = s.first, b = s.second;
  return eq(abs(b - a), abs(a - p) + abs(b - p));
}

bool isCrossSS(S s0, S s1) {
  P a = s0.first, b = s0.second;
  P c = s1.first, d = s1.second;
  int f0 = ccw(a, b, c) * ccw(a, b, d);
  int f1 = ccw(c, d, a) * ccw(c, d, b);
  return (f0 <= 0 && f1 <= 0);
}

bool isCrossLS(L l, S s) {
  P a = l.first, b = l.second;
  P c = s.first, d = s.second;
  return (ccw(a, b, c) * ccw(a, b, d) <= 0);
}

double distLP(L l, P p) {
  P a = l.first, b = l.second;
  double res = cross(b - a, p - a) / abs(b - a);
  return abs(res);
}

double distSP(S s, P p) {
  P a = s.first, b = s.second;
  if (dot(b - a, p - a) < eps)
    return abs(p - a);
  if (dot(a - b, p - b) < eps)
    return abs(p - b);
  return distLP(s, p);
}

double distSS(S s0, S s1) {
  if (isCrossSS(s0, s1))
    return 0;
  double res0 = min(distSP(s0, s1.first), distSP(s0, s1.second));
  double res1 = min(distSP(s1, s0.first), distSP(s1, s0.second));
  return min(res0, res1);
}

P getCrossLL(L l0, L l1) {
  P a = l0.first, b = l0.second;
  P c = l1.first, d = l1.second;
  a -= d;
  b -= d;
  c -= d;
  return d + a + (b - a) * imag(a / c) / imag(a / c - b / c);
}

P getVector(const vecP &t, int id) {
  int n = t.size();
  return t[(id + 1) % n] - t[id % n];
}

void pr(P p, string str = "\\n") {
  printf("%.10f %.10f", p.real(), p.imag());
  cout << str;
}

int checkPolygonP(vecP &t, P p) {
  int n = t.size();
  double sum = 0;
  for (int i = 0; i < n; i++) {
    P a = t[i], b = t[(i + 1 == n ? 0 : i + 1)];
    if (ccw(a, b, p) == 0) {
      return 1;
    }
    sum += getArg(a - p, b - p);
  }
  if (abs(sum) < eps)
    return 0;
  return 2;
}

void checkPolygonS(vecP &t, S s, int &maxm, int &mini) {
  int n = t.size();

  typedef pair<double, int> Pair;

  vector<P> u;
  vector<Pair> v;
  for (int i = 0; i < n; i++) {
    P a = t[i], b = t[(i + 1 == n ? 0 : i + 1)];
    S base = S(a, b);
    if (isParallel(base, s))
      continue;
    if (!isCrossSS(base, s))
      continue;

    P target = getCrossLL(base, s);

    assert(onLP(base, target));
    assert(onLP(s, target));

    Pair pair;
    pair.first = getTime(s.second - s.first, target - s.first);
    pair.second = u.size();
    u.push_back(target);
    v.push_back(pair);
  }

  v.push_back(Pair(0.0, u.size()));
  u.push_back(s.first);
  v.push_back(Pair(1.0, u.size()));
  u.push_back(s.second);
  sort(v.begin(), v.end());

  maxm = -1;
  mini = 3;
  for (int i = 0; i < (int)v.size(); i++) {
    int f = checkPolygonP(t, u[v[i].second]);
    maxm = max(maxm, f);
    mini = min(mini, f);
    if (i + 1 < (int)v.size()) {
      int h = checkPolygonP(t, (u[v[i].second] + u[v[i + 1].second]) * 0.5);
      maxm = max(maxm, h);
      mini = min(mini, h);
    }
  }
}

bool inPolygonS(vecP &t, S s) {
  int maxm, mini;
  checkPolygonS(t, s, maxm, mini);
  if (mini == 0)
    return false;
  return true;
}

bool outPolygonS(vecP &t, S s) {
  int maxm, mini;
  checkPolygonS(t, s, maxm, mini);
  if (maxm == 2)
    return false;
  return true;
}

void pr(P p) { printf("%.3f %.3f\\n", p.real(), p.imag()); }

////////////////

struct state {
  double cost;
  int pos;
  state(double x, int y) : cost(x), pos(y) {}
  bool operator<(const state &s) const { return cost > s.cost; }
};

P input() {
  double x, y;
  cin >> x >> y;
  return P(x, y);
}

S getS(vecP &t, int index) {
  int n = t.size();
  index %= n;
  return S(t[index], t[(index + 1) % n]);
}

double solve(vector<vecP> &a, P si, P ti, L line) {
  vecP A, B;
  for (int i = 0; i < (int)a.size(); i++) {
    if (checkPolygonP(a[i], si) > 0 && checkPolygonP(a[i], ti) > 0) {
      A = a[i];
    }
    if (checkPolygonP(a[i], reflect(line, si)) > 0 &&
        checkPolygonP(a[i], reflect(line, ti)) > 0) {
      B = a[i];
    }
  }
  if (A.empty() || B.empty())
    return -1;
  for (int i = 0; i < (int)B.size(); i++)
    B[i] = reflect(line, B[i]);
  vecP t;
  for (int i = 0; i < (int)A.size(); i++)
    t.push_back(A[i]);
  for (int i = 0; i < (int)B.size(); i++)
    t.push_back(B[i]);
  for (int i = 0; i < (int)A.size(); i++) {
    for (int j = 0; j < (int)B.size(); j++) {
      S fi = getS(A, i);
      S se = getS(B, j);
      if (!isParallel(fi, se) && isCrossSS(fi, se)) {
        t.push_back(getCrossLL(fi, se));
      }
    }
  }

  t.push_back(si);
  t.push_back(ti);
  sort(t.begin(), t.end());
  t.erase(unique(t.begin(), t.end()), t.end());

  vector<double> d(t.size(), 1e9);
  int sid = lower_bound(t.begin(), t.end(), si) - t.begin();
  int tid = lower_bound(t.begin(), t.end(), ti) - t.begin();

  d[sid] = 0;
  priority_queue<state> Q;
  Q.push(state(0, sid));
  while (!Q.empty()) {
    state s = Q.top();
    Q.pop();

    if (s.pos == tid)
      return s.cost;

    if (d[s.pos] < s.cost)
      continue;
    for (int to = 0; to < (int)t.size(); to++) {
      if (s.pos == to)
        continue;
      S path = S(t[s.pos], t[to]);
      if (!inPolygonS(A, path))
        continue;
      if (!inPolygonS(B, path))
        continue;
      double ncost = s.cost + abs(path.second - path.first);
      if (d[to] - eps > ncost) {
        d[to] = ncost;
        Q.push(state(ncost, to));
      }
    }
  }

  return -1;
}

int main() {
  int n;

  while (cin >> n && n) {

    vector<vecP> a;
    a.resize(n);
    for (int i = 0; i < n; i++) {
      int m;
      cin >> m;
      a[i].resize(m);
      for (int j = 0; j < m; j++) {
        a[i][j] = input();
      }
    }
    P si = input();
    P ti = input();

    L line;
    line.first = input();
    line.second = input();
    double ans = solve(a, si, ti, line);
    if (ans < 0) {
      printf("impossible\\n");
    } else {
      printf("%.10f\\n", ans);
    }
  }
  return 0;
}