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

#include <bits/stdc++.h>
#define double long double
using namespace std;
typedef complex<double> P; // Point
typedef pair<P, P> L;      // Line, Segment
const double EPS = 1e-9;
const double PI = 6.0 * asin(0.5);
const double INF = 1e9;
namespace std {
bool operator<(const P &a, const P &b) {
  return fabs(real(a) - real(b)) < EPS ? imag(a) < imag(b) : real(a) < real(b);
}
} // namespace std

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

int ccw(P a, P b, P c) {
  b -= a;
  c -= a;
  if (cross(b, c) > EPS)
    return 1; // ????????????(b-a)????????´???????????????(c-a)????????¨?????????
  if (cross(b, c) < -EPS)
    return -1; // ????????????(b-a)????????´???????????????(c-a)????????¨?????????
  if (dot(b, c) < -EPS)
    return 2;
  if (norm(b) < norm(c))
    return -2;
  return 0;
}

bool isIntersectLS(L l, L s) {
  return cross(l.second - l.first, s.first - l.first) *
             cross(l.second - l.first, s.second - l.first) <
         EPS;
}

double getDistanceSP(L s, P p) {
  if (dot(s.second - s.first, p - s.first) < -EPS)
    return abs(p - s.first);
  if (dot(s.first - s.second, p - s.second) < -EPS)
    return abs(p - s.second);
  return abs(cross(s.second - s.first, p - s.first) /
             abs(s.second - s.first)); //??´?????¨???????????¢
}

P crossPoint(L l, L m) {
  double A = cross(l.second - l.first, m.second - m.first);
  double B = cross(l.second - l.first, l.second - m.first);
  if (fabs(A) < EPS && fabs(B) < EPS)
    return m.first;
  else if (fabs(A) >= EPS)
    return m.first + B / A * (m.second - m.first);
}

P proj(P p, L l) {
  return l.first + dot(p - l.first, l.second - l.first) /
                       norm(l.second - l.first) * (l.second - l.first);
}

P reflect(P p, L l) { return p + (proj(p, l) - p) * (double)2.0; }

double w, h, r;
const double eps = 1e-8;
bool eq(double a, double b) { return abs(a - b) < eps; }
bool eq(P a, P b) { return eq(a.real(), b.real()) && eq(a.imag(), b.imag()); }

bool onFront(L a, P b) {
  return !eq(a.first, b) && dot(a.second - a.first, b - a.first) > 0;
}

//?????????????????????????£???????????°??????????????????????
L getNp(L p, P o, L kabe) {
  P a = (double)2 * (o - p.first) +
        p.first;          // o -> p.first????????????????????????
  P b = reflect(a, kabe); //?£????????????????????§°??????????±???????
  return L(o, b);
}

double
getTime(L a,
        P b) { //????????????????????????????????????????????????????±???????
  double d = getDistanceSP(a, b);
  if (d > 2 * r)
    return INF; //?????¢?????????*2???????????§??????
  d = abs(b - proj(b, a));
  P c = proj(b, a) - a.first; // ?°???±????????????????????????????????????
  double l =
      abs(c) - sqrt((2 * r) * (2 * r) -
                    d * d); //??§?????????|c| -
                            //sqrt(r*r-d*d)?????¨???????????????????????????
  return max((double)0, l);
}

vector<P> ball;
int solve(L p) {
  L table[4] = {L(P(r, r), P(w - r, r)), L(P(w - r, r), P(w - r, h - r)),
                L(P(w - r, h - r), P(r, h - r)), L(P(r, h - r), P(r, r))};

  double dis = 1e4;
  int n = ball.size();
  while (!eq(dis, 0)) {
    P CP;
    int idx, cnt = 0;
    for (int i = 0; i < 4; i++) {
      P a = p.second - p.first;
      a = (double)1e6 * (a / abs(a));
      if (!isIntersectLS(L(p.first, a + p.first), table[i]))
        continue;
      P cp = crossPoint(p, table[i]);
      if (!onFront(p, cp))
        continue;
      cnt++;
      CP = cp;
      idx = i;
    }

    //?????£????????¢??§???????????§?±?????????????
    if (dis < abs(CP - p.first))
      CP = dis * ((CP - p.first) / abs(CP - p.first)) + p.first;
    dis -= abs(p.first - CP);

    int res = -1;
    double d = 1e9;
    for (int i = 0; i < n; i++) {
      double t = getTime(L(p.first, CP), ball[i]);
      if (d > t)
        d = t, res = i;
    }

    if (res != -1)
      return res + 2;
    if (cnt >= 2)
      p = L(CP, p.first); //?§???????????????¨???
    else
      p = getNp(p, CP, table[idx]);
  }
  return -1;
}

int main() {

  while (1) {
    static int cnt = 0;
    int n;
    cin >> n;
    if (n == 0)
      break;
    double vx, vy;
    cin >> w >> h >> r >> vx >> vy;

    double x, y;
    cin >> x >> y;
    L start = L(P(x, y), P(x + vx, y + vy));
    ball.resize(--n);
    for (int i = 0; i < n; i++)
      cin >> x >> y, ball[i] = P(x, y);

    cout << solve(start) << endl;
  }
  return 0;
}

Error: 0

Fixed submission:

#include <bits/stdc++.h>
using namespace std;
typedef complex<double> P; // Point
typedef pair<P, P> L;      // Line, Segment
const double EPS = 1e-8;
const double PI = 6.0 * asin(0.5);
namespace std {
bool operator<(const P &a, const P &b) {
  return fabs(real(a) - real(b)) < EPS ? imag(a) < imag(b) : real(a) < real(b);
}
} // namespace std

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

int ccw(P a, P b, P c) {
  b -= a;
  c -= a;
  if (cross(b, c) > EPS)
    return 1; // ????????????(b-a)????????´???????????????(c-a)????????¨?????????
  if (cross(b, c) < -EPS)
    return -1; // ????????????(b-a)????????´???????????????(c-a)????????¨?????????
  if (dot(b, c) < -EPS)
    return 2;
  if (norm(b) < norm(c))
    return -2;
  return 0;
}

bool isIntersectLS(L l, L s) {
  return cross(l.second - l.first, s.first - l.first) *
             cross(l.second - l.first, s.second - l.first) <
         EPS;
}

double getDistanceSP(L s, P p) {
  if (dot(s.second - s.first, p - s.first) < -EPS)
    return abs(p - s.first);
  if (dot(s.first - s.second, p - s.second) < -EPS)
    return abs(p - s.second);
  return abs(cross(s.second - s.first, p - s.first) /
             abs(s.second - s.first)); //??´?????¨???????????¢
}

P crossPoint(L l, L m) {
  double A = cross(l.second - l.first, m.second - m.first);
  double B = cross(l.second - l.first, l.second - m.first);
  if (fabs(A) < EPS && fabs(B) < EPS)
    return m.first;
  else if (fabs(A) >= EPS)
    return m.first + B / A * (m.second - m.first);
}

double w, h, r;
const double eps = 1e-8;
bool eq(double a, double b) { return abs(a - b) < eps; }

bool onFront(L a, P b) {
  a.second -= a.first;
  b -= a.first;
  return dot(a.second, b) > 0;
}

L getNp(L p, P o, P n) {
  P a = o - p.first;
  P ra = -a;
  P b = n * (dot(n, ra) / abs(n));
  return L(o, 2.0 * b + o);
}

vector<P> ball;
int solve(L p) {
  L table[4] = {L(P(0, 0), P(w, 0)), L(P(w, 0), P(w, h)), L(P(w, h), P(0, h)),
                L(P(0, h), P(0, 0))};

  double dis = 1e4;

  int n = ball.size();

  while (!eq(dis, 0)) {

    vector<P> CP;
    int idx;
    for (int i = 0; i < 4; i++) {
      if (!isIntersectLS(p, table[i]))
        continue;
      P cp = crossPoint(p, table[i]);
      if (!onFront(p, cp))
        continue;
      // cout<<cp<<endl;
      CP.push_back(cp);
      idx = i;
    }

    //?????£????????¢??§???????????§?±?????????????
    if (dis - abs(p.first - CP[0]) < 0)
      CP[0] = dis * ((p.second - p.first) / abs(p.second - p.first)), dis = 0;
    else
      dis -= abs(p.first - CP[0]);

    int res = -1;
    double d = 1e9;
    for (int i = 0; i < n; i++) {
      double dd = getDistanceSP(L(p.first, CP[0]), ball[i]);
      double nd = abs(p.first - CP[0]);
      if (dd > 2 * r || d <= nd)
        continue;
      d = nd, res = i;
    }

    if (res != -1)
      return res + 2;

    if (CP.size() >= 2)
      p = L(CP[0], p.first); //?§???????????????¨???
    else
      p = getNp(p, CP[0],
                table[(idx + 1) % n].second - table[(idx + 1) % n].first);
  }
  return -1;
}

int main() {
  while (1) {
    int n;
    cin >> n;
    if (n == 0)
      break;
    double vx, vy;
    cin >> w >> h >> r >> vx >> vy;

    double x, y;
    cin >> x >> y;
    L start = L(P(x, y), P(x + vx, y + vy));
    n--;
    ball.resize(n);
    for (int i = 0; i < n; i++)
      cin >> x >> y, ball[i] = P(x, y);
    cout << solve(start) << endl;
  }
  return 0;
}