Problem p00752 (C++)

Buggy submission (status: Runtime Error):
#include <bits/stdc++.h>
using namespace std;
typedef complex<double> P;

double eps = 1e-8;

bool eq(double a, double b) { return (-eps < a - b && a - b < eps); }

bool eq(P a, P b) { return (abs(a - b) < eps); }

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

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

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

struct S {
  P p, q;
  S(P a = P(0, 0), P b = P(0, 0)) : p(a), q(b) {}
  P base() { return q - p; }
};

typedef S L;

double getDistanceLP(L l, P p) {
  P a = l.p, b = l.q;
  return abs(cross(b - a, p - a)) / abs(b - a);
}

double getDistanceSP(S s, P p) {
  P a = s.p;
  P b = s.q;
  if (dot(b - a, p - a) < eps)
    return abs(p - a);
  if (dot(a - b, p - b) < eps)
    return abs(p - b);
  return getDistanceLP(s, p);
}

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

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

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

P getCrossPoint(S s1, S s2) {
  P a = s1.p, b = s1.q;
  P c = s2.p, d = s2.q;
  a -= d, b -= d, c -= d;
  return d + a + (b - a) * imag(a / c) / imag(a / c - b / c);
}

bool isIntersectLS(L li, S se) {
  P a = li.p;
  P b = li.q;
  double A = cross(b - a, se.p - a);
  double B = cross(b - a, se.q - a);
  if (A * B < eps)
    return true;
}

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

int N;
S t[5];
P si, ti;
int tl[10];
double ans;

double calc(P p, P v, int depth) {

  if (eq(p, ti))
    return 0;

  P np, nv;

  if (depth > 6)
    return 1e20;

  double mini = 1e20;
  for (int i = 0; i < N; i++) {
    S seg = t[i];
    if (onSegment(seg, p))
      continue;

    L li = L(p, p + v);
    if (!isIntersectLS(li, seg))
      continue;

    P k = getCrossPoint(li, seg);
    assert(onSegment(seg, k));
    assert(onLine(li, k));
    /*
    cout<<"i="<<i<<endl;
    cout<<"k="<<k<<endl;
    cout<<"v="<<v<<endl;
    cout<<"p="<<p<<endl;
    cout<<endl;
    */
    if (dot(k - p, v) < 0)
      continue;

    if (mini > abs(k - p)) {
      mini = abs(k - p);
      np = k;
      nv = reflect(seg, k + v) - k;
    }
  }

  if (isParallel(v, ti - p) && dot(v, ti - p) > 0) {
    if (mini > abs(ti - p)) {
      return abs(ti - p);
    }
  }

  if (mini == 1e20)
    return 1e20;
  return mini + calc(np, nv, depth + 1);
}

P ansve;
void check(int size, P target) {
  P v = target - si;
  if (abs(v) < eps)
    return;
  double dist = calc(si, v, 0);
  if (ans > dist) {
    ans = dist;
    ansve = v;
  }
}

void dfs(int depth, P target) {
  check(depth, target);
  if (depth == 6)
    return;
  for (int i = 0; i < N; i++) {
    dfs(depth + 1, reflect(t[i], target));
  }
}

int main() {
  while (1) {
    cin >> N;
    if (N == 0)
      break;
    for (int i = 0; i < N; i++) {
      P a = input();
      P b = input();
      t[i] = S(a, b);
    }
    ti = input();
    si = input();
    ans = 1e20;
    dfs(0, ti);
    printf("%.10f\n", ans);
  }

  return 0;
}

Fixed submission:
#include <bits/stdc++.h>
using namespace std;
typedef complex<double> P;

double eps = 1e-8;

bool eq(double a, double b) { return (-eps < a - b && a - b < eps); }

bool eq(P a, P b) { return (abs(a - b) < eps); }

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

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

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

struct S {
  P p, q;
  S(P a = P(0, 0), P b = P(0, 0)) : p(a), q(b) {}
  P base() { return q - p; }
};

typedef S L;

double getDistanceLP(L l, P p) {
  P a = l.p, b = l.q;
  return abs(cross(b - a, p - a)) / abs(b - a);
}

double getDistanceSP(S s, P p) {
  P a = s.p;
  P b = s.q;
  if (dot(b - a, p - a) < eps)
    return abs(p - a);
  if (dot(a - b, p - b) < eps)
    return abs(p - b);
  return getDistanceLP(s, p);
}

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

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

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

P getCrossPoint(S s1, S s2) {
  P a = s1.p, b = s1.q;
  P c = s2.p, d = s2.q;
  a -= d, b -= d, c -= d;
  return d + a + (b - a) * imag(a / c) / imag(a / c - b / c);
}

bool isIntersectLS(L li, S se) {
  P a = li.p;
  P b = li.q;
  double A = cross(b - a, se.p - a);
  double B = cross(b - a, se.q - a);
  return (A * B < eps);
}

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

int N;
S t[5];
P si, ti;
int tl[10];
double ans;

double calc(P p, P v, int depth) {

  if (eq(p, ti))
    return 0;

  P np, nv;

  if (depth > 6)
    return 1e20;

  double mini = 1e20;
  for (int i = 0; i < N; i++) {
    S seg = t[i];
    if (onSegment(seg, p))
      continue;

    L li = L(p, p + v);
    if (!isIntersectLS(li, seg))
      continue;

    P k = getCrossPoint(li, seg);
    assert(onSegment(seg, k));
    assert(onLine(li, k));
    /*
    cout<<"i="<<i<<endl;
    cout<<"k="<<k<<endl;
    cout<<"v="<<v<<endl;
    cout<<"p="<<p<<endl;
    cout<<endl;
    */
    if (dot(k - p, v) < 0)
      continue;

    if (mini > abs(k - p)) {
      mini = abs(k - p);
      np = k;
      nv = reflect(seg, k + v) - k;
    }
  }

  if (isParallel(v, ti - p) && dot(v, ti - p) > 0) {
    if (mini > abs(ti - p)) {
      return abs(ti - p);
    }
  }

  if (mini == 1e20)
    return 1e20;
  return mini + calc(np, nv, depth + 1);
}

P ansve;
void check(int size, P target) {
  P v = target - si;
  if (abs(v) < eps)
    return;
  double dist = calc(si, v, 0);
  if (ans > dist) {
    ans = dist;
    ansve = v;
  }
}

void dfs(int depth, P target) {
  check(depth, target);
  if (depth == 6)
    return;
  for (int i = 0; i < N; i++) {
    dfs(depth + 1, reflect(t[i], target));
  }
}

int main() {
  while (1) {
    cin >> N;
    if (N == 0)
      break;
    for (int i = 0; i < N; i++) {
      P a = input();
      P b = input();
      t[i] = S(a, b);
    }
    ti = input();
    si = input();
    ans = 1e20;
    dfs(0, ti);
    printf("%.10f\n", ans);
  }

  return 0;
}