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

#include <algorithm>
#include <cmath>
#include <complex>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <vector>
using namespace std;

#define EPS 1e-9

typedef complex<double> P;
typedef const P &rP;

double pi = acos(-1.0);

int n;
double r0;
vector<P> c;
vector<double> r;
vector<P> tcs;
vector<vector<int>> tbl, rtbl;

inline double sq(double x) { return x * x; }

inline double cross(rP a, rP b) {
  return a.real() * b.imag() - b.real() * a.imag();
}

vector<P> tangent_circle(rP c1, double r1, rP c2, double r2) {
  vector<P> ret;

  double u = r0 - r1;
  double v = r0 - r2;
  double w = abs(c2 - c1);
  if (u <= 0.0 || v <= 0.0 || w <= 0.0)
    return ret;

  double theta = arg(c2 - c1);
  double cosphi = (u * u + w * w - v * v) / (2.0 * u * w);
  if (abs(cosphi) > 1.0) {
    return ret;
  }
  double phi = acos(cosphi);
  ret.push_back(c1 + polar(u, theta + phi));
  ret.push_back(c1 + polar(u, theta - phi));
  if (norm(ret[0] - ret[1]) < EPS) {
    ret.pop_back();
  }
  return ret;
}

bool check(rP c0) {
  for (int i = 0; i < n; ++i) {
    if (abs(c0 - c[i]) + r[i] - r0 > EPS) {
      return false;
    }
  }
  return true;
}

bool exists(const vector<P> &v, rP z) {
  for (int i = 0; i < v.size(); ++i) {
    if (norm(v[i] - z) < EPS) {
      return true;
    }
  }
  return false;
}

int determine(int t_num) {
  if (tbl[t_num].empty())
    while (1)
      ;
  int t = tbl[t_num][0];
  for (int i = 1; i < tbl[t_num].size(); ++i) {
    int u = tbl[t_num][i];
    if (cross(c[t] - tcs[t_num], c[u] - tcs[t_num]) > 0.0) {
      t = u;
    }
  }
  return t;
}

double difangle(double a, double b) {
  a -= b;
  while (a < EPS) {
    a += 2.0 * pi;
  }
  return a;
}

struct tancircle {
  P c;
  int m1, m2;
  int xorm;

  tancircle(rP c, int m1, int m2) : c(c), m1(m1), m2(m2), xorm(m1 ^ m2) {}
};

void solve() {
  c.clear();
  r.clear();
  double x, y;

  vector<double> r_in(n);
  vector<P> c_in(n);
  vector<char> use(n, 1);

  for (int i = 0; i < n; ++i) {
    scanf("%lf%lf%lf", &x, &y, &r_in[i]);
    c_in[i] = P(x, y);
  }

  for (int i = 0; i < n; ++i) {
    for (int j = 0; j < n; ++j) {
      if (i != j && abs(c_in[i] - c_in[j]) + r_in[i] - r_in[j] < EPS) {
        use[i] = 0;
        break;
      }
    }
  }

  for (int i = 0; i < n; ++i) {
    if (use[i]) {
      r.push_back(r_in[i]);
      c.push_back(c_in[i]);
    }
  }
  n = r.size();

  if (n == 1) {
    if (r0 >= r[0]) {
      printf("%.15f\\n", (2.0 * r0 - r[0]) * 2.0 * pi);
    } else {
      puts("0.0");
    }
    return;
  }

  tcs.clear();
  for (int i = 0; i < n; ++i)
    for (int j = i + 1; j < n; ++j) {
      vector<P> v = tangent_circle(c[i], r[i], c[j], r[j]);
      for (int k = 0; k < v.size(); ++k) {
        if (check(v[k]) && !exists(tcs, v[k])) {
          tcs.push_back(v[k]);
        }
      }
    }

  if (tcs.empty()) {
    puts("0.0");
    return;
  }

  tbl.assign(tcs.size(), vector<int>());
  rtbl.assign(n, vector<int>());

  for (int i = 0; i < tcs.size(); ++i) {
    for (int j = 0; j < n; ++j) {
      if (abs(abs(tcs[i] - c[j]) + r[j] - r0) < EPS) {
        tbl[i].push_back(j);
        rtbl[j].push_back(i);
      }
    }
  }

  int t_num = 0;
  int c_num = determine(t_num);

  double sum = 0.0;
  double base = arg(tcs[t_num] - c[c_num]);
  do {
    double mindif = 1e99;
    int minindex = -1;

    vector<int>::iterator it;
    for (it = rtbl[c_num].begin(); it != rtbl[c_num].end(); ++it) {
      double angle = arg(tcs[*it] - c[c_num]);
      double dif = difangle(angle, base);
      if (mindif > dif) {
        mindif = dif;
        minindex = *it;
      }
    }
    if (minindex < 0) {
      puts("0.0");
      return;
    }
    sum += mindif * (2.0 * r0 - r[c_num]);
    t_num = minindex;
    c_num = determine(t_num);

    double nextbase = arg(tcs[t_num] - c[c_num]);
    sum += r0 * difangle(nextbase, base + mindif);
    base = nextbase;
  } while (t_num != 0);

  printf("%.15f\\n", sum);
}

int main() {
  while (scanf("%d%lf", &n, &r0), n != 0) {
    solve();
  }
}

Error: TLE

Fixed submission:

#include <algorithm>
#include <cmath>
#include <complex>
#include <cstdio>
#include <cstring>
#include <vector>
using namespace std;

#define EPS 1e-7

typedef complex<double> P;
typedef const P &rP;

double pi = acos(-1.0);

int n;
double r0;
vector<P> c;
vector<double> r;
vector<P> tcs;
vector<vector<int>> tbl, rtbl;

inline double sq(double x) { return x * x; }

inline double cross(rP a, rP b) {
  return a.real() * b.imag() - b.real() * a.imag();
}

vector<P> tangent_circle(rP c1, double r1, rP c2, double r2) {
  vector<P> ret;

  double u = r0 - r1;
  double v = r0 - r2;
  double w = abs(c2 - c1);
  if (u <= 0.0 || v <= 0.0 || w <= 0.0)
    return ret;

  double theta = arg(c2 - c1);
  double phi = acos((u * u + w * w - v * v) / (2.0 * u * w));
  ret.push_back(c1 + polar(u, theta + phi));
  ret.push_back(c1 + polar(u, theta - phi));
  if (norm(ret[0] - ret[1]) < EPS) {
    ret.pop_back();
  }
  return ret;
}

bool check(rP c0) {
  for (int i = 0; i < n; ++i) {
    if (abs(c0 - c[i]) + r[i] - r0 > EPS) {
      return false;
    }
  }
  return true;
}

bool exists(const vector<P> &v, rP z) {
  for (int i = 0; i < v.size(); ++i) {
    if (norm(v[i] - z) < EPS) {
      return true;
    }
  }
  return false;
}

int determine(int t_num) {
  if (tbl[t_num].empty()) {
    while (1)
      ;
  }
  int t = tbl[t_num][0];
  for (int i = 1; i < tbl[t_num].size(); ++i) {
    int u = tbl[t_num][i];
    if (cross(c[t] - tcs[t_num], c[u] - tcs[t_num]) > 0.0) {
      t = u;
    }
  }
  return t;
}

double difangle(double a, double b) {
  a -= b;
  while (a < EPS) {
    a += 2.0 * pi;
  }
  return a;
}

struct tancircle {
  P c;
  int m1, m2;
  int xorm;

  tancircle(rP c, int m1, int m2) : c(c), m1(m1), m2(m2), xorm(m1 ^ m2) {}
};

void solve() {
  c.clear();
  r.clear();
  double x, y;

  vector<double> r_in(n);
  vector<P> c_in(n);
  vector<char> use(n, 1);

  for (int i = 0; i < n; ++i) {
    scanf("%lf%lf%lf", &x, &y, &r_in[i]);
    c_in[i] = P(x, y);
  }

  for (int i = 0; i < n; ++i) {
    for (int j = 0; j < n; ++j) {
      if (i != j && abs(c_in[i] - c_in[j]) + r_in[i] - r_in[j] < EPS) {
        use[i] = 0;
        break;
      }
    }
  }

  for (int i = 0; i < n; ++i) {
    if (use[i]) {
      r.push_back(r_in[i]);
      c.push_back(c_in[i]);
    }
  }
  n = r.size();

  if (n == 1) {
    if (r0 >= r[0]) {
      printf("%.15f\\n", (2.0 * r0 - r[0]) * 2.0 * pi);
    } else {
      puts("0.0");
    }
    return;
  }

  tcs.clear();
  for (int i = 0; i < n; ++i)
    for (int j = i + 1; j < n; ++j) {
      vector<P> v = tangent_circle(c[i], r[i], c[j], r[j]);
      for (int k = 0; k < v.size(); ++k) {
        if (check(v[k]) && !exists(tcs, v[k])) {
          tcs.push_back(v[k]);
        }
      }
    }

  if (tcs.empty()) {
    puts("0.0");
    return;
  }

  tbl.assign(tcs.size(), vector<int>());
  rtbl.assign(n, vector<int>());

  for (int i = 0; i < tcs.size(); ++i) {
    for (int j = 0; j < n; ++j) {
      if (abs(abs(tcs[i] - c[j]) + r[j] - r0) < EPS) {
        tbl[i].push_back(j);
        rtbl[j].push_back(i);
      }
    }
  }

  int t_num = 0;
  int c_num = determine(t_num);

  double sum = 0.0;
  double base = arg(tcs[t_num] - c[c_num]);
  do {
    double mindif = 1e99;
    int minindex = -1;

    vector<int>::iterator it;
    for (it = rtbl[c_num].begin(); it != rtbl[c_num].end(); ++it) {
      double angle = arg(tcs[*it] - c[c_num]);
      double dif = difangle(angle, base);
      if (mindif > dif) {
        mindif = dif;
        minindex = *it;
      }
    }
    if (minindex < 0) {
      puts("0.0");
      return;
    }
    sum += mindif * (2.0 * r0 - r[c_num]);
    t_num = minindex;
    c_num = determine(t_num);

    double nextbase = arg(tcs[t_num] - c[c_num]);
    sum += r0 * difangle(nextbase, base + mindif);
    base = nextbase;
  } while (t_num != 0);

  printf("%.15f\\n", sum);
}

int main() {
  while (scanf("%d%lf", &n, &r0), n != 0) {
    solve();
  }
}