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

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

const double INF = 1e+9;
const double EPS = 1e-6;
const double EPS2 = 1e-7;
const int N = 10;
const double H = 100.0;
const double W = H;

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

struct P3 {
  double x, y, z;
  P3(double x = 0, double y = 0, double z = 0) : x(x), y(y), z(z) {}
  P3(P p, double z) : x(real(p)), y(imag(p)), z(z) {}
  P3 operator+(const P3 &a) const { return P3(x + a.x, y + a.y, z + a.z); }
  P3 operator-(const P3 &a) const { return P3(x - a.x, y - a.y, z - a.z); }
  P3 operator*(const double &c) const { return P3(x * c, y * c, z * c); }
};
P3 operator*(double c, const P3 &a) { return P3(c * a.x, c * a.y, c * a.z); }

struct L3 {
  P3 a, b;
  L3(P3 a = P3(), P3 b = P3()) : a(a), b(b) {}
};

struct Stick {
  P p;
  double h;
  Stick(P p = P(), double h = 0) : p(p), h(h) {}
};

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

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

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

double abs(P3 a) { return sqrt(a.x * a.x + a.y * a.y + a.z * a.z); }

double dot(P3 a, P3 b) { return a.x * b.x + a.y * b.y + a.z * b.z; }

double distSP(L3 S, P3 p) {
  double a = dot(S.b - S.a, S.b - S.a);
  double b = dot(S.b - S.a, S.a - p);
  double c = dot(S.a - p, S.a - p);
  double t = -b / a;

  if (t < -EPS)
    return abs(S.a - p);
  if (t > 1.0 + EPS)
    return abs(S.b - p);
  return sqrt(max(0.0, (a * t * t + 2.0 * b * t + c)));
}

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

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

vector<P> getIntersectCC(Circle c1, Circle c2) {
  vector<P> res;
  double r1 = c1.r, r2 = c2.r, d;
  P p1 = c1.c, p2 = c2.c;
  d = abs(p1 - p2);

  if (d < EPS && abs(r1 - r2) < EPS)
    return res; //????????¨?????????????????´???????????????????????????????????????
  if (r1 + r2 < d - EPS || d + EPS < abs(r1 - r2))
    return res; //???????????????

  double a = (r1 * r1 - r2 * r2 + d * d) / (2 * d);
  double h = sqrt(max(r1 * r1 - a * a, 0.0));
  P tmp1 = p1 + a / d * (p2 - p1);
  P tmp2 = h / d * (p2 - p1);

  if (abs(tmp2) < EPS)
    res.push_back(tmp1);
  else {
    res.push_back(P(real(tmp1) - imag(tmp2), imag(tmp1) + real(tmp2)));
    res.push_back(P(real(tmp1) + imag(tmp2), imag(tmp1) - real(tmp2)));
  }
  return res;
}

double getIntersectStC(Stick s, Circle c) {
  return distSP(L3(P3(s.p, 0), P3(s.p, s.h)), P3(c.c, c.r));
}

bool isIntersectStC(Stick s, Circle c) {
  return distSP(L3(P3(s.p, 0), P3(s.p, s.h)), P3(c.c, c.r)) < c.r - EPS;
}

double getIntersectR(Stick s, double cr) {
  double le = 0, ri = INF, mid;

  while (fabs(ri - le) > EPS2) {
    mid = (le + ri) / 2.0;
    if (isIntersectStC(s, Circle(P(real(s.p) + mid, imag(s.p)), cr)))
      le = mid;
    else
      ri = mid;
  }

  return ri;
}

int n;
double w;
vector<Stick> v;

bool check(P p) {
  double x = real(p);
  double y = imag(p);
  if (x < -EPS || x > W + EPS)
    return false;
  if (y < -EPS || y > H + EPS)
    return false;
  return true;
}

bool is_hit(double cr) {
  vector<L> vl;
  vector<Circle> vc;
  vector<P> resv;

  for (int i = 0; i < n; i++) {
    vc.push_back(Circle(P(v[i].p), getIntersectR(v[i], cr)));
  }

  double rr = getIntersectR(Stick(P(0, 0), w), cr);
  vl.push_back(L(P(0, rr), P(W, rr)));
  vl.push_back(L(P(W - rr, 0), P(W - rr, H)));
  vl.push_back(L(P(W, H - rr), P(0, H - rr)));
  vl.push_back(L(P(rr, H), P(rr, 0)));

  for (int i = 0; i < n; i++) {
    for (int j = i + 1; j < n; j++) {
      vector<P> res = getIntersectCC(vc[i], vc[j]);
      for (int k = 0; k < res.size(); k++) {
        if (check(res[k]))
          resv.push_back(res[k]);
      }
      if (res.size() == 2) {
        if (check((res[0] + res[1]) / 2.0)) {
          resv.push_back((res[0] + res[1]) / 2.0);
        }
      }
    }
    for (int j = 0; j < 4; j++) {
      vector<P> res = getIntersectCS(vc[i], vl[j]);
      for (int k = 0; k < res.size(); k++) {
        if (check(res[k]))
          resv.push_back(res[k]);
      }
      if (res.size() == 2) {
        if (check(res[0] + res[1]) / 2.0) {
          resv.push_back((res[0] + res[1]) / 2.0);
        }
      }
    }
  }

  if (rr < H + EPS) {
    resv.push_back(P(rr, rr));
  }

  for (int i = 0; i < resv.size(); i++) {
    bool f = true;
    Circle c = Circle(resv[i], cr);
    for (int j = 0; j < n; j++) {
      if (isIntersectStC(v[j], c)) {
        f = false;
        break;
      }
    }
    if (f && !isIntersectStC(Stick(P(0, imag(c.c)), w), c) &&
        !isIntersectStC(Stick(P(real(c.c), 0), w), c) &&
        !isIntersectStC(Stick(P(W, imag(c.c)), w), c) &&
        !isIntersectStC(Stick(P(real(c.c), H), w), c)) {
      /*
      cout << c.c << " : " << endl;
      for(int j=0;j<n;j++) {
        cout << cr << ": " << v[j].p << ' ' << getIntersectStC(v[j], c) << endl;
      }
      cout << P(0, imag(c.c)) << ' ' << getIntersectStC(Stick(P(0, imag(c.c)),
      w), c) << endl; cout << P(W, imag(c.c)) << ' ' <<
      getIntersectStC(Stick(P(W, imag(c.c)), w), c) << endl; cout <<
      P(real(c.c), 0) << ' ' << getIntersectStC(Stick(P(real(c.c), 0), w), c) <<
      endl; cout << P(real(c.c), H) << ' ' << getIntersectStC(Stick(P(real(c.c),
      H), w), c) << endl;
      */
      return false;
    }
  }

  return true;
}

double solve() {
  double le = 0, ri = INF, mid;

  while (fabs(ri - le) > EPS2) {
    mid = (le + ri) / 2.0;
    if (is_hit(mid))
      ri = mid;
    else
      le = mid;
  }
  return (le + ri) / 2.0;
}

int main() {
  double x, y, h;
  while (cin >> n >> w && n) {
    v.clear();
    for (int i = 0; i < n; i++) {
      cin >> x >> y >> h;
      v.push_back(Stick(P(x, y), h));
    }
    printf("%.5f\\n", solve());
  }
}

Error: TLE

Fixed submission:

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

const double INF = 1e+9;
const double EPS = 1e-6;
const double EPS2 = 1e-8;
const int N = 10;
const double H = 100.0;
const double W = H;

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

struct P3 {
  double x, y, z;
  P3(double x = 0, double y = 0, double z = 0) : x(x), y(y), z(z) {}
  P3(P p, double z) : x(real(p)), y(imag(p)), z(z) {}
  P3 operator+(const P3 &a) const { return P3(x + a.x, y + a.y, z + a.z); }
  P3 operator-(const P3 &a) const { return P3(x - a.x, y - a.y, z - a.z); }
  P3 operator*(const double &c) const { return P3(x * c, y * c, z * c); }
};
P3 operator*(double c, const P3 &a) { return P3(c * a.x, c * a.y, c * a.z); }

struct L3 {
  P3 a, b;
  L3(P3 a = P3(), P3 b = P3()) : a(a), b(b) {}
};

struct Stick {
  P p;
  double h;
  Stick(P p = P(), double h = 0) : p(p), h(h) {}
};

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

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

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

double abs(P3 a) { return sqrt(a.x * a.x + a.y * a.y + a.z * a.z); }

double dot(P3 a, P3 b) { return a.x * b.x + a.y * b.y + a.z * b.z; }

double distSP(L3 S, P3 p) {
  double a = dot(S.b - S.a, S.b - S.a);
  double b = dot(S.b - S.a, S.a - p);
  double c = dot(S.a - p, S.a - p);
  double t = -b / a;

  if (t < -EPS)
    return abs(S.a - p);
  if (t > 1.0 + EPS)
    return abs(S.b - p);
  return sqrt(max(0.0, (a * t * t + 2.0 * b * t + c)));
}

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

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

vector<P> getIntersectCC(Circle c1, Circle c2) {
  vector<P> res;
  double r1 = c1.r, r2 = c2.r, d;
  P p1 = c1.c, p2 = c2.c;
  d = abs(p1 - p2);

  if (d < EPS && abs(r1 - r2) < EPS)
    return res; //????????¨?????????????????´???????????????????????????????????????
  if (r1 + r2 < d - EPS || d + EPS < abs(r1 - r2))
    return res; //???????????????

  double a = (r1 * r1 - r2 * r2 + d * d) / (2 * d);
  double h = sqrt(max(r1 * r1 - a * a, 0.0));
  P tmp1 = p1 + a / d * (p2 - p1);
  P tmp2 = h / d * (p2 - p1);

  if (abs(tmp2) < EPS)
    res.push_back(tmp1);
  else {
    res.push_back(P(real(tmp1) - imag(tmp2), imag(tmp1) + real(tmp2)));
    res.push_back(P(real(tmp1) + imag(tmp2), imag(tmp1) - real(tmp2)));
  }
  return res;
}

double getIntersectStC(Stick s, Circle c) {
  return distSP(L3(P3(s.p, 0), P3(s.p, s.h)), P3(c.c, c.r));
}

bool isIntersectStC(Stick s, Circle c) {
  return distSP(L3(P3(s.p, 0), P3(s.p, s.h)), P3(c.c, c.r)) < c.r - EPS;
}

double getIntersectR(Stick s, double cr) {
  double le = 0, ri = INF, mid;

  while (fabs(ri - le) > EPS2) {
    mid = (le + ri) / 2.0;
    if (isIntersectStC(s, Circle(P(real(s.p) + mid, imag(s.p)), cr)))
      le = mid;
    else
      ri = mid;
  }

  return ri;
}

int n;
double w;
vector<Stick> v;

bool check(P p) {
  double x = real(p);
  double y = imag(p);
  if (x < -EPS && x > W + EPS)
    return false;
  if (y < -EPS && y > H + EPS)
    return false;
  return true;
}

bool is_hit(double cr) {
  vector<L> vl;
  vector<Circle> vc;
  vector<P> resv;

  for (int i = 0; i < n; i++) {
    vc.push_back(Circle(P(v[i].p), getIntersectR(v[i], cr)));
  }

  double rr = getIntersectR(Stick(P(0, 0), w), cr);
  vl.push_back(L(P(0, rr), P(W, rr)));
  vl.push_back(L(P(W - rr, 0), P(W - rr, H)));
  vl.push_back(L(P(W, H - rr), P(0, H - rr)));
  vl.push_back(L(P(rr, H), P(rr, 0)));

  for (int i = 0; i < n; i++) {
    for (int j = i + 1; j < n; j++) {
      vector<P> res = getIntersectCC(vc[i], vc[j]);
      for (int k = 0; k < res.size(); k++) {
        if (check(res[k]))
          resv.push_back(res[k]);
      }
      if (res.size() == 2) {
        if (check((res[0] + res[1]) / 2.0)) {
          resv.push_back((res[0] + res[1]) / 2.0);
        }
      }
    }
    for (int j = 0; j < 4; j++) {
      vector<P> res = getIntersectCS(vc[i], vl[j]);
      for (int k = 0; k < res.size(); k++) {
        if (check(res[k]))
          resv.push_back(res[k]);
      }
      if (res.size() == 2) {
        if (check(res[0] + res[1]) / 2.0) {
          resv.push_back((res[0] + res[1]) / 2.0);
        }
      }
    }
  }

  if (rr < H + EPS) {
    resv.push_back(P(rr, rr));
  }

  for (int i = 0; i < resv.size(); i++) {
    bool f = true;
    Circle c = Circle(resv[i], cr);
    for (int j = 0; j < n; j++) {
      if (isIntersectStC(v[j], c)) {
        f = false;
        break;
      }
    }
    if (f && !isIntersectStC(Stick(P(0, imag(c.c)), w), c) &&
        !isIntersectStC(Stick(P(real(c.c), 0), w), c) &&
        !isIntersectStC(Stick(P(W, imag(c.c)), w), c) &&
        !isIntersectStC(Stick(P(real(c.c), H), w), c)) {
      return false;
    }
  }

  return true;
}

double solve() {
  double le = 0, ri = INF, mid;

  while (fabs(ri - le) > EPS2) {
    mid = (le + ri) / 2.0;
    if (is_hit(mid))
      ri = mid;
    else
      le = mid;
  }
  return (le + ri) / 2.0;
}

int main() {
  double x, y, h;
  while (cin >> n >> w && n) {
    v.clear();
    for (int i = 0; i < n; i++) {
      cin >> x >> y >> h;
      v.push_back(Stick(P(x, y), h));
    }
    printf("%.5f\\n", solve());
  }
}