Problem p01649 (C++) — buggy submission, verdict: Time Limit Exceeded

#include <bits/stdc++.h>
#define double long double
using namespace std;

typedef complex<double> P;
typedef pair<P, P> L;

const double EPS = 1e-8;

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

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

bool isIntersectSP(L s, P p) {
  return abs(s.first - p) + abs(s.second - p) - abs(s.second - s.first) < EPS;
}

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) {
  double x = 2;
  P res = p + (proj(p, l) - p) * x;
  int a = res.real() + 0.5, b = res.imag() + 0.5;
  res = P((double)a, (double)b);
  return res;
}

struct Circle {
  P c;      //?????????
  double r; //??????
  Circle(P c = P(0, 0), double r = 0) : c(c), r(r) {}
};

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;
}

vector<P> getIntersectCL(Circle c, L l) {
  vector<P> res;
  P h = proj(c.c, l);
  double d = abs(c.c - h);
  if (d > c.r + EPS)
    ;
  else if (d > c.r - EPS)
    res.push_back(h);
  else {
    P v = l.second - l.first;
    v = (sqrt(c.r * c.r - d * d) / abs(v)) * v;
    res.push_back(h + v);
    res.push_back(h - v);
  }
  return res;
}

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;
}

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);
}

int n, w, h, r, vx, vy;
P p, ball[12], recWS;

void mirror(L l) {
  for (int i = 0; i < n; i++)
    ball[i] = reflect(ball[i], l);
}

bool isinrec(P point) {

  double y1 = recWS.imag(), y2 = y1 + h;
  double x1 = recWS.real(), x2 = x1 + w;

  return y1 <= point.imag() && point.imag() <= y2 && x1 <= point.real() &&
         point.real() <= x2;
}

void solve() {

  if (vy < 0) {
    vy = abs(vy);
    L N = L(P(0, h), P(w, h));
    p = reflect(p, N);
    p = P(p.real(), p.imag() - h);
    mirror(N);
    for (int i = 0; i < n; i++)
      ball[i] = P(ball[i].real(), ball[i].imag() - h);
  }

  if (vx < 0) {
    vx = abs(vx);
    L E = L(P(w, 0), P(w, h));
    p = reflect(p, E);
    p = P(p.real() - w, p.imag());
    mirror(E);
    for (int i = 0; i < n; i++)
      ball[i] = P(ball[i].real() - w, ball[i].imag());
  }

  int ans = -3;
  double mindis = 1e9;

  L l = L(p, P(p.real() + vx, p.imag() + vy));

  while (1) {

    if (abs(recWS - p) > 1e4)
      break;

    for (int i = 0; i < n; i++) {

      Circle c = Circle(ball[i], r);
      vector<P> v = getIntersectCL(c, l);

      for (int j = 0; j < v.size(); j++) {
        if (dot(l.second - p, v[j] - p) < 0)
          continue;
        if (1e4 < abs(p - v[j]))
          continue;

        if (isinrec(v[j]) && mindis > abs(p - v[j])) {
          mindis = abs(p - v[j]);
          ans = i;
        }
      }
    }

    L N = L(P(recWS.real(), recWS.imag() + h),
            P(recWS.real() + w, recWS.imag() + h));
    L E = L(P(recWS.real() + w, recWS.imag()),
            P(recWS.real() + w, recWS.imag() + h));

    int f1 = 0, f2 = 0;

    if (isIntersectLS(l, N))
      f1 = 1;
    if (isIntersectLS(l, E))
      f2 = 1;
    /*
    P tmp = P(recWS.real()+w, recWS.imag()+h);
    if(abs(ccw(l.first, l.second, tmp))!=1) f1=1, f2=1;
    */
    if (f1) {
      mirror(N);
      recWS = P(recWS.real(), recWS.imag() + h);
    }

    if (f2) {
      mirror(E);
      recWS = P(recWS.real() + w, recWS.imag());
    }
  }

  cout << ans + 2 << endl;
}

int main() {

  while (1) {

    recWS = P(0, 0);

    cin >> n;
    if (!n)
      break;

    n--;

    cin >> w >> h >> r >> vx >> vy;

    int x, y;
    cin >> x >> y;

    p = P(x - r, y - r);

    for (int i = 0; i < n; i++) {
      cin >> x >> y;
      ball[i] = P(x - r, y - r);
    }

    r *= 2;
    w -= r, h -= r;

    solve();
  }

  return 0;
}

Error: TLE

Fixed submission:

#include <bits/stdc++.h>
#define double long double
using namespace std;

typedef complex<double> P;
typedef pair<P, P> L;

const double EPS = 1e-8;

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

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

bool isIntersectSP(L s, P p) {
  return abs(s.first - p) + abs(s.second - p) - abs(s.second - s.first) < EPS;
}

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) {
  double x = 2;
  return p + (proj(p, l) - p) * x;
}

struct Circle {
  P c;      //?????????
  double r; //??????
  Circle(P c = P(0, 0), double r = 0) : c(c), r(r) {}
};

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;
}

vector<P> getIntersectCL(Circle c, L l) {
  vector<P> res;
  P h = proj(c.c, l);
  double d = abs(c.c - h);
  if (d > c.r + EPS)
    ;
  else if (d > c.r - EPS)
    res.push_back(h);
  else {
    P v = l.second - l.first;
    v = (sqrt(c.r * c.r - d * d) / abs(v)) * v;
    res.push_back(h + v);
    res.push_back(h - v);
  }
  return res;
}

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;
}

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);
}

int n, w, h, r, vx, vy;
P p, ball[12], recWS;

void mirror(L l) {
  for (int i = 0; i < n; i++)
    ball[i] = reflect(ball[i], l);
}

bool isinrec(P point) {

  double y1 = recWS.imag(), y2 = y1 + h;
  double x1 = recWS.real(), x2 = x1 + w;

  return y1 - EPS <= point.imag() && point.imag() <= y2 + EPS &&
         x1 - EPS <= point.real() && point.real() <= x2 + EPS;
}

void solve() {

  /*  cout<<h<<' '<<w<<endl;
      cout<<p.real()<<' '<<p.imag()<<endl;*/

  if (vy < 0) {
    vy = abs(vy);
    L N = L(P(0, h), P(w, h));

    assert(p.imag() <= h + EPS);

    reflect(p, N);
    p = P(p.real(), p.imag() - h);

    // cout<<p.real()<<' '<<p.imag()<<endl;
    //     assert(isinrec(p));

    // if(p.imag()<-1) assert(0);

    mirror(N);
    for (int i = 0; i < n; i++)
      ball[i] = P(ball[i].real(), ball[i].imag() - h);
  }

  if (vx < 0) {
    vx = abs(vx);
    L E = L(P(w, 0), P(w, h));
    reflect(p, E);
    p = P(p.real() - w, p.imag());
    mirror(E);
    for (int i = 0; i < n; i++)
      ball[i] = P(ball[i].real() - w, ball[i].imag());
  }

  int ans = -3;
  double mindis = 1e9;

  L l = L(p, P(p.real() + vx, p.imag() + vy));
  int cnt = 0;
  while (1) {

    if (abs(recWS - p) > 1e4)
      break;

    for (int i = 0; i < n; i++) {

      Circle c = Circle(ball[i], r);
      vector<P> v = getIntersectCL(c, l);

      for (int j = 0; j < v.size(); j++) {

        if (1e4 < abs(p - v[j]))
          continue;

        if (isinrec(v[j]) && mindis > abs(p - v[j])) {
          mindis = abs(p - v[j]);
          ans = i;
        }
      }
    }

    L N = L(P(recWS.real(), recWS.imag() + h),
            P(recWS.real() + w, recWS.imag() + h));
    L E = L(P(recWS.real() + w, recWS.imag()),
            P(recWS.real() + w, recWS.imag() + h));

    int f1 = 0, f2 = 0;

    if (isIntersectLS(l, N))
      f1 = 1;
    if (isIntersectLS(l, E))
      f2 = 1;

    if (f1) {
      mirror(N);
      recWS = P(recWS.real(), recWS.imag() + h);
    }

    if (f2) {
      mirror(E);
      recWS = P(recWS.real() + w, recWS.imag());
    }

    // if(!f1&&!f2&&(F1||F2)) assert(cnt);
    // if(!F1&&!F2) assert(f1||f2);
    cnt++;
  }

  cout << ans + 2 << endl;
}

int main() {

  while (1) {

    recWS = P(0, 0);

    cin >> n;
    if (!n)
      break;

    n--;

    cin >> w >> h >> r >> vx >> vy;

    int x, y;
    cin >> x >> y;

    p = P(x - r, y - r);

    for (int i = 0; i < n; i++) {
      cin >> x >> y;
      ball[i] = P(x - r, y - r);
    }

    r *= 2;
    w -= r, h -= r;

    solve();
  }

  return 0;
}