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

#include <algorithm>
#include <array>
#include <cmath>
#include <complex>
#include <iomanip>
#include <iostream>
#include <vector>
using namespace std;

const double EPS = 1e-10;
const double INF = 1e12;
#define EQ(n, m) (abs((n) - (m)) < EPS)
#define X real()
#define Y imag()

typedef complex<double> P;
typedef vector<P> VP;
struct L : array<P, 2> {
  L(const P &a, const P &b) {
    at(0) = a;
    at(1) = b;
  }
  L() {}
};

namespace std {
bool operator<(const P &a, const P &b) {
  return (a.X != b.X) ? a.X < b.X : a.Y < b.Y;
}
bool operator==(const P &a, const P &b) { return abs(a - b) < EPS; }
} // namespace std

double dot(P a, P b) { return (conj(a) * b).X; }
double cross(P a, P b) { return (conj(a) * b).Y; }
int ccw(P a, P b, P c) {
  b -= a;
  c -= a;
  if (cross(b, c) > EPS)
    return +1; // ccw
  if (cross(b, c) < -EPS)
    return -1; // cw
  if (dot(b, c) < -EPS)
    return +2; // c-a-b
  if (abs(c) - abs(b) > EPS)
    return -2; // a-b-c
  return 0;    // a-c-b
}
P unit(const P &p) { return p / abs(p); }

bool isParallel(const P &a, const P &b) { return abs(cross(a, b)) < EPS; }
bool isParallel(const L &a, const L &b) {
  return isParallel(a[1] - a[0], b[1] - b[0]);
}

bool intersectLS(const L &l, const L &s) {
  return cross(l[1] - l[0], s[0] - l[0]) * cross(l[1] - l[0], s[1] - l[0]) <
         EPS;
}
bool intersectSS(const L &a, const L &b) {
  return (ccw(a[0], a[1], b[0]) * ccw(a[0], a[1], b[1]) <= 0) &&
         (ccw(b[0], b[1], a[0]) * ccw(b[0], b[1], a[1]) <= 0);
}
bool intersectSP(const L &s, const P &p) {
  return abs(s[0] - p) + abs(s[1] - p) - abs(s[1] - s[0]) < EPS;
}
P crosspointLL(const L &l, const L &m) {
  double A = cross(l[1] - l[0], m[1] - m[0]);
  double B = cross(l[1] - l[0], l[1] - m[0]);
  return m[0] + B / A * (m[1] - m[0]);
}

double L1distance(const P &a, const P &b) {
  return abs(b.X - a.X) + abs(b.Y - a.Y);
}
double L1distanceSP(const L &s, const P &p) {
  double ret = INF;
  for (int i = 0; i < 2; i++) {
    L gl(p, p + P(i, 1 - i));
    if (!isParallel(s, gl) && intersectLS(gl, s)) {
      P cp = crosspointLL(s, L(p, p + P(i, 1 - i)));
      ret = min(ret, abs(p - cp));
    }
    ret = min(ret, L1distance(p, s[i]));
  }
  return ret;
}

int in_poly(const P &p, const VP &poly) {
  int n = poly.size();
  int cn = 0;
  for (int i = 0; i < n; i++) {
    if (intersectSP(L(poly[i], poly[(i + 1) % n]), p)) {
      return 0;
    }
  }
  L ray(p, p + P(INF, 0));
  for (int i = 0; i < n; i++) {
    if ((poly[i].Y <= p.Y && poly[(i + 1) % n].Y > p.Y) ||
        (poly[i].Y > p.Y && poly[(i + 1) % n].Y <= p.Y)) {
      if (intersectSS(ray, L(poly[i], poly[(i + 1) % n]))) {
        cn++;
      }
    }
  }
  if (cn % 2 != 0)
    return 1;
  else
    return -1;
}
vector<L> arrangement(const vector<L> &e) {
  VP cp;
  cp.reserve(e.size() * e.size());
  for (int i = 0; i < (int)e.size(); i++) {
    for (int j = i + 1; j < (int)e.size(); j++) {
      if (!isParallel(e[i], e[j]) && intersectSS(e[i], e[j])) {
        cp.push_back(crosspointLL(e[i], e[j]));
      }
    }
  }
  sort(cp.begin(), cp.end());
  cp.erase(unique(cp.begin(), cp.end()), cp.end());

  vector<L> ret;
  for (int i = 0; i < (int)e.size(); i++) {
    VP vlist;
    vlist.reserve(e.size());
    for (int j = 0; j < (int)cp.size(); j++) {
      if (intersectSP(e[i], cp[j])) {
        vlist.push_back(cp[j]);
      }
    }
    for (int j = 0; j < (int)vlist.size() - 1; j++) {
      ret.push_back(L(vlist[j], vlist[j + 1]));
    }
  }
  sort(ret.begin(), ret.end());
  ret.erase(unique(ret.begin(), ret.end()), ret.end());
  return ret;
}

int main() {
  while (1) {
    int n, r;
    cin >> n >> r;
    if (n == 0)
      break;

    VP v(n);
    for (int i = 0; i < n; i++) {
      double x, y;
      cin >> x >> y;
      v[i] = P(x, y);
    }
    vector<VP> sq(n, VP(4));
    for (int i = 0; i < n; i++) {
      sq[i][0] = v[i] + P(r, 0);
      sq[i][1] = v[i] + P(0, r);
      sq[i][2] = v[i] + P(-r, 0);
      sq[i][3] = v[i] + P(0, -r);
    }

    vector<L> l;
    l.reserve(9 * n);
    for (int i = 0; i < n; i++) {
      l.push_back(L(v[i], v[(i + 1) % n]));
      for (int j = 0; j < 4; j++) {
        l.push_back(L(sq[i][j], sq[(i + 1) % n][j]));
        l.push_back(L(sq[i][j], sq[i][(j + 1) % 4]));
      }
    }
    vector<L> cand = arrangement(l);

    double ans = 0;
    for (int i = 0; i < (int)cand.size(); i++) {
      bool rem = true;
      for (int j = 0; j < n; j++) {
        P mid = (cand[i][0] + cand[i][1]) / 2.0;
        if (L1distanceSP(L(v[j], v[(j + 1) % n]), mid) + EPS < r ||
            in_poly(mid, v) == -1) {
          rem = false;
          break;
        }
      }
      if (rem) {
        ans += abs(cand[i][1] - cand[i][0]);
      }
    }
    cout << fixed;
    cout << setprecision(10);
    cout << ans << endl;
  }
  return 0;
}


Error: TLE

Fixed submission:

#include <algorithm>
#include <array>
#include <cmath>
#include <complex>
#include <iomanip>
#include <iostream>
#include <vector>
using namespace std;

const double EPS = 1e-10;
const double INF = 1e12;
#define EQ(n, m) (abs((n) - (m)) < EPS)
#define X real()
#define Y imag()

typedef complex<double> P;
typedef vector<P> VP;
struct L : array<P, 2> {
  L(const P &a, const P &b) {
    at(0) = a;
    at(1) = b;
  }
  L() {}
};

namespace std {
bool operator<(const P &a, const P &b) {
  return (a.X != b.X) ? a.X < b.X : a.Y < b.Y;
}
bool operator==(const P &a, const P &b) { return abs(a - b) < EPS; }
} // namespace std

double dot(P a, P b) { return (conj(a) * b).X; }
double cross(P a, P b) { return (conj(a) * b).Y; }
int ccw(P a, P b, P c) {
  b -= a;
  c -= a;
  if (cross(b, c) > EPS)
    return +1; // ccw
  if (cross(b, c) < -EPS)
    return -1; // cw
  if (dot(b, c) < -EPS)
    return +2; // c-a-b
  if (abs(c) - abs(b) > EPS)
    return -2; // a-b-c
  return 0;    // a-c-b
}
P unit(const P &p) { return p / abs(p); }

bool isParallel(const P &a, const P &b) { return abs(cross(a, b)) < EPS; }
bool isParallel(const L &a, const L &b) {
  return isParallel(a[1] - a[0], b[1] - b[0]);
}

bool intersectLS(const L &l, const L &s) {
  return cross(l[1] - l[0], s[0] - l[0]) * cross(l[1] - l[0], s[1] - l[0]) <
         EPS;
}
bool intersectSS(const L &a, const L &b) {
  return (ccw(a[0], a[1], b[0]) * ccw(a[0], a[1], b[1]) <= 0) &&
         (ccw(b[0], b[1], a[0]) * ccw(b[0], b[1], a[1]) <= 0);
}
bool intersectSP(const L &s, const P &p) {
  return abs(s[0] - p) + abs(s[1] - p) - abs(s[1] - s[0]) < EPS;
}
P crosspointLL(const L &l, const L &m) {
  double A = cross(l[1] - l[0], m[1] - m[0]);
  double B = cross(l[1] - l[0], l[1] - m[0]);
  return m[0] + B / A * (m[1] - m[0]);
}

double L1distance(const P &a, const P &b) {
  return abs(b.X - a.X) + abs(b.Y - a.Y);
}
double L1distanceSP(const L &s, const P &p) {
  double ret = INF;
  for (int i = 0; i < 2; i++) {
    L gl(p, p + P(i, 1 - i));
    if (!isParallel(s, gl) && intersectLS(gl, s)) {
      P cp = crosspointLL(s, L(p, p + P(i, 1 - i)));
      ret = min(ret, abs(p - cp));
    }
    ret = min(ret, L1distance(p, s[i]));
  }
  return ret;
}

int in_poly(const P &p, const VP &poly) {
  int n = poly.size();
  int cn = 0;
  for (int i = 0; i < n; i++) {
    if (intersectSP(L(poly[i], poly[(i + 1) % n]), p)) {
      return 0;
    }
  }
  L ray(p, p + P(INF, 0));
  for (int i = 0; i < n; i++) {
    if ((poly[i].Y <= p.Y && poly[(i + 1) % n].Y > p.Y) ||
        (poly[i].Y > p.Y && poly[(i + 1) % n].Y <= p.Y)) {
      if (intersectSS(ray, L(poly[i], poly[(i + 1) % n]))) {
        cn++;
      }
    }
  }
  if (cn % 2 != 0)
    return 1;
  else
    return -1;
}
vector<L> arrangement(const vector<L> &e) {
  VP cp;
  for (int i = 0; i < (int)e.size(); i++) {
    for (int j = i + 1; j < (int)e.size(); j++) {
      if (!isParallel(e[i], e[j])) {
        cp.push_back(crosspointLL(e[i], e[j]));
      }
    }
  }
  sort(cp.begin(), cp.end());
  cp.erase(unique(cp.begin(), cp.end()), cp.end());

  vector<L> ret;
  for (int i = 0; i < (int)e.size(); i++) {
    VP vlist;
    for (int j = 0; j < (int)cp.size(); j++) {
      if (intersectSP(e[i], cp[j])) {
        vlist.push_back(cp[j]);
      }
    }
    for (int j = 0; j < (int)vlist.size() - 1; j++) {
      ret.push_back(L(vlist[j], vlist[j + 1]));
    }
  }
  sort(ret.begin(), ret.end());
  ret.erase(unique(ret.begin(), ret.end()), ret.end());
  return ret;
}

int main() {
  while (1) {
    int n, r;
    cin >> n >> r;
    if (n == 0)
      break;

    VP v(n);
    for (int i = 0; i < n; i++) {
      double x, y;
      cin >> x >> y;
      v[i] = P(x, y);
    }
    vector<VP> sq(n, VP(4));
    for (int i = 0; i < n; i++) {
      sq[i][0] = v[i] + P(r, 0);
      sq[i][1] = v[i] + P(0, r);
      sq[i][2] = v[i] + P(-r, 0);
      sq[i][3] = v[i] + P(0, -r);
    }

    vector<L> l;
    for (int i = 0; i < n; i++) {
      l.push_back(L(v[i], v[(i + 1) % n]));
      for (int j = 0; j < 4; j++) {
        l.push_back(L(sq[i][j], sq[(i + 1) % n][j]));
        l.push_back(L(sq[i][j], sq[i][(j + 1) % 4]));
      }
    }
    vector<L> cand = arrangement(l);

    double ans = 0;
    for (int i = 0; i < (int)cand.size(); i++) {
      bool rem = true;
      for (int j = 0; j < n; j++) {
        P mid = (cand[i][0] + cand[i][1]) / 2.0;
        if (L1distanceSP(L(v[j], v[(j + 1) % n]), mid) + EPS < r ||
            in_poly(mid, v) == -1) {
          rem = false;
          break;
        }
      }
      if (rem) {
        ans += abs(cand[i][1] - cand[i][0]);
      }
    }
    cout << fixed;
    cout << setprecision(10);
    cout << ans << endl;
  }
  return 0;
}