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

#include <algorithm>
#include <math.h>
#include <stdio.h>
#include <vector>
using namespace std;
const double EPS = 1e-5;
const double INF = 1e+10;
const double PI = acos(-1);
int sig(double r) { return (r < -EPS) ? -1 : (r > +EPS) ? +1 : 0; }
inline double ABS(double a) { return max(a, -a); }
struct Pt {
  double x, y;
  Pt() {}
  Pt(double x, double y) : x(x), y(y) {}
  Pt operator+(const Pt &a) const { return Pt(x + a.x, y + a.y); }
  Pt operator-(const Pt &a) const { return Pt(x - a.x, y - a.y); }
  Pt operator*(const Pt &a) const {
    return Pt(x * a.x - y * a.y, x * a.y + y * a.x);
  }
  Pt operator-() const { return Pt(-x, -y); }
  Pt operator*(const double &k) const { return Pt(x * k, y * k); }
  Pt operator/(const double &k) const { return Pt(x / k, y / k); }
  double ABS() const { return sqrt(x * x + y * y); }
  double abs2() const { return x * x + y * y; }
  double arg() const { return atan2(y, x); }
  double dot(const Pt &a) const { return x * a.x + y * a.y; }
  double det(const Pt &a) const { return x * a.y - y * a.x; }
};
inline bool operator<(const Pt &a, const Pt &b) {
  if (a.x != b.x)
    return a.x < b.x;
  return a.y < b.y;
}
double tri(const Pt &a, const Pt &b, const Pt &c) { return (b - a).det(c - a); }
int iSP(Pt a, Pt b, Pt c) {
  int s = sig((b - a).det(c - a));
  if (s)
    return s;
  if (sig((b - a).dot(c - a)) < 0)
    return -2; // c-a-b
  if (sig((a - b).dot(c - b)) < 0)
    return +2; // a-b-c
  return 0;
}
int iLL(Pt a, Pt b, Pt c, Pt d) {
  if (sig((b - a).det(d - c)))
    return 1; // intersect
  if (sig((b - a).det(c - a)))
    return 0; // parallel
  return -1;  // correspond
}
bool iLS(Pt a, Pt b, Pt c, Pt d) {
  return (sig(tri(a, b, c)) * sig(tri(a, b, d)) <= 0);
}
Pt pLL(Pt a, Pt b, Pt c, Pt d) {
  b = b - a;
  d = d - c;
  return a + b * (c - a).det(d) / b.det(d);
}
bool iSS(Pt a, Pt b, Pt c, Pt d) {
  return (iSP(a, b, c) * iSP(a, b, d) <= 0 && iSP(c, d, a) * iSP(c, d, b) <= 0);
}
bool iSSstrict(Pt a, Pt b, Pt c, Pt d) {
  return (sig(tri(a, b, c)) * sig(tri(a, b, d)) < 0 &&
          sig(tri(c, d, a)) * sig(tri(c, d, b)) < 0);
}
int n;
Pt pl[20];
int can[20][1100];
int sGP(Pt a) {
  int side = -1, i;
  for (i = 0; i < n; ++i) {
    Pt p0 = pl[i] - a, p1 = pl[i + 1] - a;
    if (sig(p0.det(p1)) == 0 && sig(p0.dot(p1)) <= 0)
      return 0;
    if (p0.y > p1.y)
      swap(p0, p1);
    if (sig(p0.y) <= 0 && 0 < sig(p1.y) && sig(p0.det(p1)) > 0)
      side = -side;
  }
  return side;
}
int main() {
  int a;
  while (scanf("%d", &a), a) {
    n = a;
    for (int i = 0; i < a; i++) {
      double x, y;
      scanf("%lf%lf", &x, &y);
      pl[i] = Pt(x, y);
    }
    pl[a] = pl[0];
    vector<Pt> v;
    for (int i = 0; i < a; i++) {
      for (int j = i + 1; j < a; j++) {
        for (int k = 0; k < a; k++) {
          if (iLL(pl[i], pl[j], pl[k], pl[k + 1]) == 1 &&
              iLS(pl[i], pl[j], pl[k], pl[k + 1])) {
            v.push_back(pLL(pl[i], pl[j], pl[k], pl[k + 1]));
          }
        }
      }
    }
    for (int i = 0; i < a; i++)
      for (int j = 0; j < v.size(); j++)
        can[i][j] = 0;
    for (int i = 0; i < a; i++) {
      for (int j = 0; j < v.size(); j++) {
        bool ok = true;
        vector<Pt> tmp;
        tmp.push_back(pl[i]);
        tmp.push_back(v[j]);
        for (int k = 0; k < a; k++) {
          if (iSSstrict(pl[i], v[j], pl[k], pl[k + 1])) {
            ok = false;
            break;
          }
          if (iLL(pl[i], v[j], pl[k], pl[k + 1]) == 1 &&
              iSS(pl[i], v[j], pl[k], pl[k + 1])) {
            tmp.push_back(pLL(pl[i], v[j], pl[k], pl[k + 1]));
          }
        }
        if (!ok)
          continue;
        std::sort(tmp.begin(), tmp.end());
        for (int k = 0; k < tmp.size() - 1; k++) {
          if (sGP((tmp[k] + tmp[k + 1]) / 2) == -1) {
            ok = false;
            break;
          }
        }
        if (ok) {
          can[i][j] = 1;
          //		printf("(%f, %f) -> (%f,
          //%f)\\n",pl[i].x,pl[i].y,v[j].x,v[j].y);
        }
      }
    }
    int ret = a;
    for (int i = 0; i < (1 << a); i++) {
      bool ok = true;
      for (int j = 0; j < v.size(); j++) {
        bool OK = false;
        for (int k = 0; k < a; k++) {
          if (i & (1 << k)) {
            if (can[k][j])
              OK = true;
          }
        }
        if (!OK)
          ok = false;
      }
      if (ok)
        ret = min(ret, __builtin_popcount(i));
    }
    printf("%d\\n", ret);
  }
}

Error: TLE

Fixed submission:

#include <algorithm>
#include <math.h>
#include <stdio.h>
using namespace std;
double x[20];
double y[20];
double Abs(int a) { return max(a, -a); }
const double EPS = 1e-10;
const double INF = 1e+6;
const double PI = acos(-1);
int sig(double r) { return (r < -EPS) ? -1 : (r > +EPS) ? +1 : 0; }
struct Pt {
  double x, y;
  Pt() {}
  Pt(double x, double y) : x(x), y(y) {}
  Pt operator+(const Pt &a) const { return Pt(x + a.x, y + a.y); }
  Pt operator-(const Pt &a) const { return Pt(x - a.x, y - a.y); }
  Pt operator*(const Pt &a) const {
    return Pt(x * a.x - y * a.y, x * a.y + y * a.x);
  }
  Pt operator-() const { return Pt(-x, -y); }
  Pt operator*(const double &k) const { return Pt(x * k, y * k); }
  Pt operator/(const double &k) const { return Pt(x / k, y / k); }
  bool operator==(const Pt &a) const { return x == a.x && y == a.y; }
  bool operator<(const Pt &a) const {
    return (a.x != x) ? (a.x < x) : (a.y < y);
  }
  double Abs() const { return sqrt(x * x + y * y); }
  double Abs2() const { return x * x + y * y; }
  double arg() const { return atan2(y, x); }
  double dot(const Pt &a) const { return x * a.x + y * a.y; }
  double det(const Pt &a) const { return x * a.y - y * a.x; }
};
double tri(const Pt &a, const Pt &b, const Pt &c) { return (b - a).det(c - a); }
int iSP(Pt a, Pt b, Pt c) {
  int s = sig((b - a).det(c - a));
  if (s)
    return s;
  if (sig((b - a).dot(c - a)) < 0)
    return -2;
  if (sig((a - b).dot(c - b)) < 0)
    return +2;
  return 0;
}
int iLL(Pt a, Pt b, Pt c, Pt d) {
  if (sig((b - a).det(d - c)))
    return 1;
  if (sig((b - a).det(c - a)))
    return 0;
  return -1;
}
bool iLS(Pt a, Pt b, Pt c, Pt d) {
  return (sig(tri(a, b, c)) * sig(tri(a, b, d)) <= 0);
}
Pt pLL(Pt a, Pt b, Pt c, Pt d) {
  b = b - a;
  d = d - c;
  return a + b * (c - a).det(d) / b.det(d);
}
int sGP(int n, Pt p[], Pt a) {
  int side = -1, i;
  p[n] = p[0];
  for (i = 0; i < n; i++) {
    Pt p0 = p[i] - a, p1 = p[i + 1] - a;
    if (sig(p0.det(p1)) == 0 && sig(p0.dot(p1)) <= 0)
      return 0;
    if (p0.y > p1.y)
      swap(p0, p1);
    if (sig(p0.y) <= 0 && 0 < sig(p1.y) && sig(p0.det(p1)) > 0)
      side = -side;
  }
  return side;
}
int sAP(Pt a, Pt b, Pt c) {
  return sig(a.det(c)) - sig(b.det(c)) - sig(a.det(b));
}
int s_a[500], s_b[500], s_ab[500];
bool iGSstrict(int n, Pt p[], Pt a, Pt b) {
  int i;
  p[n] = p[0];
  p[n + 1] = p[1];
  if (sGP(n, p, a) > 0 || sGP(n, p, b) > 0)
    return 1;
  for (i = 0; i <= n; i++) {
    s_a[i] = sig(tri(p[i], p[i + 1], a));
    s_b[i] = sig(tri(p[i], p[i + 1], b));
    s_ab[i] = sig(tri(a, b, p[i]));
  }
  for (i = 0; i < n; i++) {
    if (s_a[i] * s_b[i] < 0 && s_ab[i] * s_ab[i + 1] < 0)
      return 1;
  }
  for (i = 0; i < n; i++) {
    if (s_a[i] == 0 && s_b[i] > 0 && sig((a - p[i]).dot(a - p[i + 1])) < 0)
      return 1;
    if (s_b[i] == 0 && s_a[i] > 0 && sig((b - p[i]).dot(b - p[i + 1])) < 0)
      return 1;
  }
  for (i = 0; i < n; i++)
    if (s_ab[i + 1] == 0 && sig((p[i + 1] - a).dot(p[i + 1] - b)) <= 0) {
      if (!(p[i + 1] == a) &&
          sAP(p[i + 2] - p[i + 1], p[i] - p[i + 1], a - p[i + 1]) > 0)
        return 1;
      if (!(p[i + 1] == b) &&
          sAP(p[i + 2] - p[i + 1], p[i] - p[i + 1], b - p[i + 1]) > 0)
        return 1;
    }
  return 0;
}
Pt point[20];
Pt val[10000];
Pt poly[300];
int main() {
  int a;
  while (scanf("%d", &a), a) {
    int S = 0;
    for (int i = 0; i < a; i++) {
      scanf("%lf%lf", x + i, y + i);
      if (x[S] < x[i])
        S = i;
      point[i] = Pt(x[i], y[i]);
    }
    int ret = 9999;
    int N = 5 + a;
    poly[0] = Pt(INF, INF);
    poly[1] = Pt(-INF, INF);
    poly[2] = Pt(-INF, -INF);
    poly[3] = Pt(INF, -INF);
    poly[4] = Pt(INF, INF - EPS);
    for (int i = 0; i < a; i++)
      poly[5 + i] = point[(S - i + a) % a];
    int Sz = 0;
    for (int i = 0; i < a; i++) {
      for (int j = i + 1; j < a; j++) {
        for (int k = 0; k < a; k++) {
          if (iLL(point[i], point[j], point[k], point[(k + 1) % a]) == 1 &&
              iLS(point[i], point[j], point[k], point[(k + 1) % a])) {
            val[Sz++] = pLL(point[i], point[j], point[k], point[(k + 1) % a]);
          }
        }
      }
    }
    std::sort(val, val + Sz);
    int sz = 0;
    for (int i = 0; i < Sz; i++) {
      if (i == 0 || (val[i] - val[i - 1]).Abs2() > EPS) {
        val[sz++] = val[i];
      }
    }
    //	for(int i=0;i<sz;i++)printf("%f %f\\n",val[i].x,val[i].y);
    for (int i = 0; i < (1 << a); i++) {
      bool ok = true;
      for (int j = 0; j < sz; j++) {
        bool OK = false;
        for (int k = 0; k < a; k++) {
          if (!(i & (1 << k)))
            continue;
          if (!iGSstrict(N, poly, point[k], val[j])) {
            OK = true;
            break;
          }
        }
        if (!OK) {
          ok = false;
          break;
        }
      }
      if (ok) {
        ret = min(ret, __builtin_popcount(i));
      }
    }
    printf("%d\\n", ret);
  }
}