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

#include <algorithm>
#include <cmath>
#include <cstdio>

#define rep(i, n) for (int i = 0; i < (n); i++)

using namespace std;

const double INF = 1e77;

template <class T> struct point {
  T x, y;
  point operator+(const point &a) const { return (point){x + a.x, y + a.y}; }
  point operator-(const point &a) const { return (point){x - a.x, y - a.y}; }
};

template <class T> struct segment {
  point<T> a, b;
};

template <class T> T dot(const point<T> &a, const point<T> &b) {
  return a.x * b.x + a.y * b.y;
}

template <class T> T cross(const point<T> &a, const point<T> &b) {
  return a.x * b.y - a.y * b.x;
}

enum { CCW = 1, CW = -1, ON = 0 };
template <class T>
int ccw(const point<T> &a, const point<T> &b, const point<T> &c) {
  T rdir = cross(b - a, c - a);
  if (rdir > 0)
    return CCW;
  if (rdir < 0)
    return CW;
  return ON;
}

template <class T> bool intersect(const segment<T> &S1, const segment<T> &S2) {
  if (max(S1.a.x, S1.b.x) < min(S2.a.x, S2.b.x) ||
      max(S1.a.y, S1.b.y) < min(S2.a.y, S2.b.y) ||
      max(S2.a.x, S2.b.x) < min(S1.a.x, S1.b.x) ||
      max(S2.a.y, S2.b.y) < min(S1.a.y, S1.b.y))
    return false;
  return ccw(S1.a, S1.b, S2.a) * ccw(S1.a, S1.b, S2.b) <= 0 &&
         ccw(S2.a, S2.b, S1.a) * ccw(S2.a, S2.b, S1.b) <= 0;
}

template <class T> T dist2(const point<T> &a, const point<T> &b) {
  return (a.x - b.x) * (a.x - b.x) + (a.y - b.y) * (a.y - b.y);
}

template <class T> double dist2(const segment<T> &S, const point<T> &p) {
  if (dot(S.b - S.a, p - S.a) <= 0)
    return dist2(p, S.a);
  if (dot(S.a - S.b, p - S.b) <= 0)
    return dist2(p, S.b);
  return (double)cross(S.b - S.a, p - S.a) * cross(S.b - S.a, p - S.a) /
         dist2(S.a, S.b);
}

template <class T> double dist(const segment<T> &S1, const segment<T> &S2) {
  if (intersect(S1, S2))
    return 0;
  return sqrt(min(min(dist2(S1, S2.a), dist2(S1, S2.b)),
                  min(dist2(S2, S1.a), dist2(S2, S1.b))));
}

int main() {
  for (int n; scanf("%d", &n), n;) {
    point<int> s, t;
    scanf("%d%d%d%d", &s.x, &s.y, &t.x, &t.y);

    double r = INF;
    while (n--) {
      int x1, y1, x2, y2, h;
      scanf("%d%d%d%d%d", &x1, &y1, &x2, &y2, &h);
      point<int> a = {x1, y1}, b = {x2, y1}, c = {x2, y2}, d = {x1, y2};

      if (x1 <= min(s.x, t.x) && max(s.x, t.x) <= x2 && y1 <= min(s.y, t.y) &&
          max(s.y, t.y) <= y2)
        r = 0; // ツ板?つェツ静シツ閉ェツづーツ閉「ツづ?づ?つ「ツづゥ

      // ツ板?づ個暗ェツ氾板凝淞つ「ツづ?つアツづォツつゥツづァツ静シツ閉ェツづ慊づ?づ個催?短ツ仰猟猟」
      double l = INF;
      l = min(l, dist((segment<int>){s, t}, (segment<int>){a, b}));
      l = min(l, dist((segment<int>){s, t}, (segment<int>){b, c}));
      l = min(l, dist((segment<int>){s, t}, (segment<int>){c, d}));
      l = min(l, dist((segment<int>){s, t}, (segment<int>){d, a}));

      if (l < h)
        r = min(r, l);
      else
        r = min(r, (l * l + h * h) / (2 * h));
    }

    printf("%.9f\\n", r);
  }

  return 0;
}

Error: TLE

Fixed submission:

/**************** Geometrical Library ****************/

#include <algorithm>
#include <cmath>
#include <vector>

#define EPS 1e-9

enum { CCW = 1, CW = -1, ON = 0 };

#define mp make_pair
#define pb push_back

using namespace std;

class Point {
public:
  double x, y;
  Point() {}
  Point(double xx, double yy) : x(xx), y(yy) {}
};

class Line : public vector<Point> {
public:
  Line(const Point &a, const Point &b) { pb(a), pb(b); }
};

class Segment : public Line {
public:
  Segment(const Point &a, const Point &b) : Line(a, b) {}
};

class Polygon : public vector<Point> {};

class Circle {
public:
  Point c;
  double r;
  Circle() {}
  Circle(const Point &cc, double rr) : c(cc), r(rr) {}
};

Point &operator+=(Point &a, const Point &b) {
  a.x += b.x, a.y += b.y;
  return a;
}

Point &operator-=(Point &a, const Point &b) {
  a.x -= b.x, a.y -= b.y;
  return a;
}

Point &operator*=(Point &a, double c) {
  a.x *= c, a.y *= c;
  return a;
}

Point &operator/=(Point &a, double c) {
  a.x /= c, a.y /= c;
  return a;
}

Point operator+(const Point &a, const Point &b) {
  Point c = a;
  return c += b;
}

Point operator-(const Point &a, const Point &b) {
  Point c = a;
  return c -= b;
}

Point operator*(double c, const Point &a) {
  Point b = a;
  return b *= c;
}

Point operator/(const Point &a, double c) {
  Point b = a;
  return b /= c;
}

bool operator<(const Point &a, const Point &b) {
  return (a.x == b.x) ? (a.y < b.y) : (a.x < b.x);
}

bool operator>(const Point &a, const Point &b) { return b < a; }

double dot(const Point &a, const Point &b) { return a.x * b.x + a.y * b.y; }

double cross(const Point &a, const Point &b) { return a.x * b.y - a.y * b.x; }

double norm2(const Point &a) { return dot(a, a); }

int ccw(const Point &a, Point b, Point c) {
  b -= a, c -= a;
  double rotdir = cross(b, c);
  if (rotdir > EPS)
    return CCW;
  if (rotdir < -EPS)
    return CW;
  return ON;
}

inline void calc_abc(const Line &l, double &a, double &b,
                     double &c) { // l : ax+by+c=0
  a = l[0].y - l[1].y;
  b = l[1].x - l[0].x;
  c = l[0].x * l[1].y - l[1].x * l[0].y;
}

Point perp_foot(const Point &p, const Line &l) {
  double a, b, c;
  calc_abc(l, a, b, c);
  return p - (a * p.x + b * p.y + c) / (a * a + b * b) * Point(a, b);
}

bool intersect(const Line &l, const Line &m, Point *p = NULL) {
  // this routine also returns true in case "M is on L", etc,.
  if (abs(cross(l[1] - l[0], m[1] - m[0])) > EPS ||
      abs(cross(l[1] - l[0], m[0] - l[0])) < EPS) {
    if (p) {
      double a1, b1, c1, a2, b2, c2;
      calc_abc(l, a1, b1, c1);
      calc_abc(m, a2, b2, c2);
      double det = a1 * b2 - a2 * b1;
      if (abs(det) < EPS)
        *p = l[0]; // l == m
      else {
        p->x = (b1 * c2 - b2 * c1) / det;
        p->y = (a2 * c1 - a1 * c2) / det;
      }
    }
    return true;
  }
  return false;
}

bool intersect(const Segment &s, const Segment &t, Point *p = NULL) {
  if (max(s[0].x, s[1].x) < min(t[0].x, t[1].x) ||
      max(t[0].x, t[1].x) < min(s[0].x, s[1].x) ||
      max(s[0].y, s[1].y) < min(t[0].y, t[1].y) ||
      max(t[0].y, t[1].y) < min(s[0].y, s[1].y))
    return false;

  if (ccw(s[0], s[1], t[0]) * ccw(s[0], s[1], t[1]) <= 0 &&
      ccw(t[0], t[1], s[0]) * ccw(t[0], t[1], s[1]) <= 0) {
    if (p) {
      double a1, b1, c1, a2, b2, c2;
      calc_abc(s, a1, b1, c1);
      calc_abc(t, a2, b2, c2);
      double det = a1 * b2 - a2 * b1;
      if (abs(det) < EPS) { // s is parallel to t
        Point q[3] = {s[0], s[1], t[0]};
        for (int i = 0; i < 3; i++) {
          if (dot(q[i] - s[0], q[i] - s[1]) < EPS &&
              dot(q[i] - t[0], q[i] - t[1]) < EPS) {
            *p = q[i];
            break;
          }
        }
      } else {
        p->x = (b1 * c2 - b2 * c1) / det;
        p->y = (a2 * c1 - a1 * c2) / det;
      }
    }
    return true;
  }
  return false;
}

/**************** Library END ****************/

#include <cstdio>

int main() {
  for (int n; scanf("%d", &n), n;) {
    Point s, g;
    scanf("%lf%lf%lf%lf", &s.x, &s.y, &g.x, &g.y);
    Segment course(s, g);
    if (s.x == g.x && s.y == g.y)
      break;
    double rmin = 1e30;
    for (int i = 0; i < n; i++) {
      Point obj[2];
      int h;
      scanf("%lf%lf%lf%lf%d", &obj[0].x, &obj[0].y, &obj[1].x, &obj[1].y, &h);

      bool oncourse = false;
      for (int j = 0; j < 2; j++)
        for (int k = 0; k < 2; k++) { // cross course x object
          Segment edge(Point(obj[j].x, obj[k].y),
                       Point(obj[k].x, obj[1 - j].y));
          if (intersect(course, edge)) {
            oncourse = true;
            break;
          }
        }
      for (int l = 0; l < 2; l++) { // course in object
        int cnt = 0;
        for (int j = 0; j < 2; j++)
          for (int k = 0; k < 2; k++) {
            Segment edge(Point(obj[j].x, obj[k].y),
                         Point(obj[k].x, obj[1 - j].y));
            cnt += ccw(edge[0], edge[1], course[l]);
          }
        if (cnt == 4 * CCW || cnt == 4 * CW) {
          oncourse = true;
          break;
        }
      }
      if (oncourse) {
        rmin = 0;
        break;
      }

      double d2min = 1e30;
      for (int j = 0; j < 2; j++)
        for (int k = 0; k < 2; k++) {
          Point u = Point(obj[j].x, obj[k].y);
          Point v = perp_foot(u, Line(course[0], course[1]));
          if (dot(v - course[0], v - course[1]) < EPS) { // v is on course
            double d2 = norm2(v - u);
            d2min = min(d2min, d2);
          }
        }
      for (int l = 0; l < 2; l++) {
        for (int j = 0; j < 2; j++)
          for (int k = 0; k < 2; k++) {
            Segment edge(Point(obj[j].x, obj[k].y),
                         Point(obj[k].x, obj[1 - j].y));
            Point v = perp_foot(course[l], Line(edge[0], edge[1]));
            if (dot(v - edge[0], v - edge[1]) < EPS) {
              double d2 = norm2(v - course[l]);
              d2min = min(d2min, d2);
            }
          }
      }

      double r;
      if (h * h < d2min)
        r = (d2min + h * h) / (2 * h);
      else
        r = sqrt(d2min);
      rmin = min(rmin, r);
    }

    printf("%f\\n", rmin);
  }

  return 0;
}