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

#include <algorithm>
#include <complex>
#include <iostream>
#include <vector>

using namespace std;

const double EPS = 1e-4;

typedef complex<double> P;

inline double dot(const P &a, const P &b) {
  return a.real() * b.real() + a.imag() * b.imag();
}

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

inline int cmp(double a, double b) {
  const double diff = a - b;
  if (fabs(diff) < EPS)
    return 0;
  return diff < 0 ? -1 : 1;
}

bool intersectSS(const P &pa, const P &pb, const P &qa, const P &qb) {
  if (cmp(cross(pb - pa, qa - pa) * cross(pb - pa, qb - pa), 0) >= 0)
    return false;
  if (cmp(cross(qb - qa, pa - qa) * cross(qb - qa, pb - qa), 0) >= 0)
    return false;
  return true;
}

bool intersectLS(const P &pa, const P &pb, const P &qa, const P &qb) {
  return cmp(cross(pb - pa, qa - pa) * cross(pb - pa, qb - pa), 0) < 0;
}

P intersection(const P &pa, const P &pb, const P &qa, const P &qb) {
  const double A = cross(pb - pa, qb - qa);
  const double B = cross(pb - pa, pb - qa);
  if (cmp(A, 0) == 0 && cmp(B, 0) == 0)
    return qa;
  return qa + B / A * (qb - qa);
}

bool in_polygon(const P &p, const vector<P> &polygon) {
  const int N = polygon.size();
  int cnt = 0;
  for (int i = 0; i < N; ++i) {
    const int ni = (i + 1) % N;
    P va = polygon[i] - p;
    P vb = polygon[ni] - p;
    if (va.imag() > vb.imag())
      swap(va, vb);
    if (cmp(va.imag(), 0) <= 0 && cmp(0, vb.imag()) < 0) {
      if (cmp(cross(va, vb), 0) < 0)
        ++cnt;
    }
    if (cmp(cross(va, vb), 0) == 0 && cmp(dot(va, vb), 0) <= 0)
      return true;
  }
  return cnt % 2 == 1;
}

bool can_see(const P &pa, const P &pb, const vector<P> &polygon) {
  const int N = polygon.size();
  if (abs(pa - pb) < EPS)
    return true;
  vector<P> ps;
  for (int i = 0; i < N; ++i) {
    const int ni = (i + 1) % N;
    if (abs(polygon[i] - pb) < EPS)
      continue;
    // if(abs(polygon[ni]-pb) < EPS) continue;
    if (intersectSS(pa, pb, polygon[i], polygon[ni]))
      return false;
    if (cmp(cross(pb - pa, polygon[i] - pa), 0) == 0 &&
        cmp(dot(pa - polygon[i], pb - polygon[i]), 0) <= 0) {
      ps.push_back(polygon[i]);
    }
  }
  ps.push_back(pa);
  ps.push_back(pb);
  sort(ps.begin(), ps.end(), [pa](const P &p1, const P &p2) {
    return norm(pa - p1) < norm(pa - p2);
  });
  for (int i = 0; i + 1 < ps.size(); ++i) {
    if (!in_polygon((ps[i] + ps[i + 1]) * 0.5, polygon))
      return false;
  }
  return true;
}

bool solve() {
  int N;
  cin >> N;
  if (!N)
    return false;

  vector<P> polygon(N);
  for (int i = 0; i < N; ++i) {
    double x, y;
    cin >> x >> y;
    polygon[i] = P(x, y);
  }
  vector<P> new_polygon;
  for (int i = 0; i < N; ++i) {
    const P pa = polygon[i];
    const P pb = polygon[(i + 1) % N];
    new_polygon.push_back(pa);
    vector<P> buf;
    for (int j = 0; j < N; ++j) {
      const P pj = polygon[j];
      for (int k = 0; k < j; ++k) {
        const P pk = polygon[k];
        if (!intersectLS(pj, pk, pa, pb))
          continue;
        const P ip = intersection(pj, pk, pa, pb);
        buf.push_back(ip);
      }
    }
    sort(buf.begin(), buf.end(),
         [pa](const P &a, const P &b) { return norm(pa - a) < norm(pa - b); });
    new_polygon.insert(new_polygon.end(), buf.begin(), buf.end());
  }
  const int M = new_polygon.size();
  vector<vector<bool>> visible_mask(N, vector<bool>(M, false));
  for (int j = 0; j < N; ++j) {
    const P p = polygon[j];
    for (int i = 0; i < M; ++i) {
      const int ni = (i + 1) % M;
      if (can_see(p, new_polygon[i], polygon) &&
          can_see(p, new_polygon[ni], polygon)) {
        visible_mask[j][i] = true;
      }
    }
  }
  int ans = N;
  for (int pat = 0; pat < (1 << N); ++pat) {
    int popcnt = 0;
    vector<bool> mask(M, false);
    for (int i = 0; i < N; ++i) {
      if (pat & (1 << i)) {
        ++popcnt;
        for (int j = 0; j < M; ++j) {
          mask[j] = mask[j] | visible_mask[i][j];
        }
      }
    }
    if (all_of(mask.begin(), mask.end(), [](bool b) { return b; })) {
      ans = min(ans, popcnt);
    }
  }
  cout << ans << endl;
  return true;
}

int main() {
  cin.tie(0);
  ios::sync_with_stdio(0);

  while (solve())
    ;
  return 0;
}

Error: TLE

Fixed submission:

#include <algorithm>
#include <complex>
#include <iostream>
#include <vector>

using namespace std;

const double EPS = 1e-9;

typedef complex<double> P;

inline double dot(const P &a, const P &b) {
  return a.real() * b.real() + a.imag() * b.imag();
}

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

inline int cmp(double a, double b) {
  const double diff = a - b;
  if (fabs(diff) < EPS)
    return 0;
  return diff < 0 ? -1 : 1;
}

bool intersect(const P &pa, const P &pb, const P &qa, const P &qb) {
  if (cross(pb - pa, qa - pa) * cross(pb - pa, qb - pa) >= 0)
    return false;
  if (cross(qb - qa, pa - qa) * cross(qb - qa, pb - qa) >= 0)
    return false;
  return true;
}

bool in_polygon(const P &p, const vector<P> &polygon) {
  const int N = polygon.size();
  int cnt = 0;
  for (int i = 0; i < N; ++i) {
    const int ni = (i + 1) % N;
    // cout << polygon[i] << polygon[ni] << p << cross(polygon[ni]-polygon[i],
    // p-polygon[i]) << endl;
    if (cmp(cross(polygon[ni] - polygon[i], p - polygon[i]), 0) == 0 &&
        cmp(dot(polygon[ni] - p, polygon[i] - p), 0) <= 0)
      return true;
    if ((cmp(polygon[i].imag(), p.imag()) <= 0 &&
         cmp(polygon[ni].imag(), p.imag()) > 0) ||
        (cmp(polygon[ni].imag(), p.imag()) <= 0 &&
         cmp(polygon[i].imag(), p.imag()) > 0)) {
      double vt = (p.imag() - polygon[i].imag()) /
                  (polygon[ni].imag() - polygon[i].imag());
      if (p.real() < (polygon[i].real() +
                      (vt * (polygon[ni].real() - polygon[i].real())))) {
        // cout << "intersect " << p << polygon[i] << polygon[ni] << endl;
        ++cnt;
      }
    }
  }
  // cout << p << cnt << endl;
  return cnt % 2 == 1;
}

bool can_see(int a, int b, const vector<P> &polygon) {
  const int N = polygon.size();
  const P pa = polygon[a];
  const P pb = polygon[b];
  const P delta = (pb - pa) / abs(pb - pa) * 0.5;
  for (int i = 0; i < N; ++i) {
    const int ni = (i + 1) % N;
    if (abs(polygon[i] - pb) < EPS)
      continue;
    if (abs(polygon[ni] - pb) < EPS)
      continue;
    if (cmp(cross(pb - pa, polygon[i] - pa), 0) == 0 &&
        dot(pa - polygon[i], pb - polygon[i]) <= 0) {
      const P cp = polygon[i] + delta;
      if (!in_polygon(cp, polygon))
        return false;
    } else if (intersect(pa, pb, polygon[i], polygon[ni]))
      return false;
  }
  return true;
}

bool solve() {
  int N;
  cin >> N;
  if (!N)
    return false;

  vector<P> polygon(N);
  for (int i = 0; i < N; ++i) {
    double x, y;
    cin >> x >> y;
    polygon[i] = P(x, y);
  }
  vector<bool> visible(N);
  int ans = N;
  for (int pat = 0; pat < (1 << N); ++pat) {
    // for(int pat = 0; pat < 2; ++pat) {
    fill(visible.begin(), visible.end(), false);
    int popcnt = 0;
    for (int i = 0; i < N; ++i) {
      if (!(pat & (1 << i)))
        continue;
      ++popcnt;
      visible[i] = true;
      for (int j = 0; j < N; ++j) {
        if (can_see(i, j, polygon)) {
          // cout << i << ' ' << j << endl;
          visible[j] = true;
        }
      }
    }
    bool ok = true;
    for (int i = 0; i < N; ++i) {
      if (!visible[i])
        ok = false;
    }
    if (ok) {
      // if(popcnt == 1) cout << "pat " << pat << endl;
      ans = min(ans, popcnt);
    }
  }
  cout << ans << endl;
  return true;
}

int main() {
  cin.tie(0);
  ios::sync_with_stdio(0);

  while (solve())
    ;
  return 0;
}