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

#include <algorithm>
#include <cmath>
#include <cstdio>
#include <cstring>
#include <vector>

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

using namespace std;

const double EPS = 1e-8;
const double INF = 1e77;

struct point {
  double x, y;
  point() : x(0), y(0) {}
  point(double x, double y) : x(x), y(y) {}
  point operator-(const point &a) const { return point(x - a.x, y - a.y); }
  bool operator==(const point &a) const {
    return abs(x - a.x) < EPS && abs(y - a.y) < EPS;
  }
};

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

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

inline double area(const point &a, const point &b, const point &c) {
  return abs(cross(b - a, c - a)) / 2;
}

int n;
point P[40];

int K;
double ans;
point Q[40], Q_ans[40];
bool vis[40];

int ub;
void dfs(int i, double a) { // a: area of the polygon Q[0...i-1]
  ub++;
  if (ub > 10000)
    return; // テヲツ慊?ゥツ?ゥティツァツ」テ」ツ?凝」ツ?ゥテ」ツ??」ツ?凝」ツ?古ァツ「ツコテ、ツソツ。テ」ツ?ァテ」ツ?催」ツ?ェテ」ツ?湘」ツ?ヲテ」ツつづ・ツ債?・ツ按?」ツ?淌」ツ?湘」ツ?陛」ツつ禿ィツェツソテ」ツ?ケテ」ツ?淌」ツつ嘉ヲツ可禿」ツ?。テ・ツ按?」ツつ?..

  if (i == K) {
    if (a < ans) {
      ans = a;
      memcpy(Q_ans, Q, sizeof Q);
    }
    return;
  }

  // pruning
  // テ・ツ?凖ィツ」ツ愿ァツつケテ」ツ?ョテヲツ閉ーテ」ツ?古ィツカツウテ」ツつ甘」ツ?ェテ」ツ?湘」ツ?ェテ」ツ?」テ」ツ?淌」ツつ嘉ヲツ可禿」ツ?。テ・ツ按?」ツつ?
  int m = 0, next[40]; // next candidates
  rep(j, n) {
    if (!vis[j] && ccw(Q[i - 2], Q[i - 1], P[j]) == CCW &&
        ccw(Q[i - 1], P[j], Q[0]) == CCW)
      next[m++] = j;
  }
  if (m < K - i)
    return;

  // pruning
  // テゥツ敖「テァツゥツ催」ツ?古、ツサツ甘」ツ?セテ」ツ?ァテ」ツ?ョテヲツ慊?・ツーツ湘」ツつ津ィツカツ?」ツ?暗」ツ?淌」ツつ嘉ヲツ可禿」ツ?。テ・ツ按?」ツつ?
  double da = INF;
  rep(j, m) da = min(da, area(Q[i - 1], P[next[j]], Q[0]));
  if (ans < a + da + EPS)
    return;

  double res = INF;
  rep(j, m) {
    Q[i] = P[next[j]];
    vis[next[j]] = true;
    dfs(i + 1, a + area(Q[0], Q[i - 1], Q[i]));
    vis[next[j]] = false;
  }
}

int main() {
  scanf("%d", &n);
  rep(i, n) scanf("%lf%lf", &P[i].x, &P[i].y);

  int q;
  scanf("%d", &q);
  int k[40], perm[40];
  rep(i, q) scanf("%d", k + i);
  {
    pair<int, int> tmp[40];
    rep(i, q) tmp[i] = make_pair(k[i], i);
    sort(tmp, tmp + q);
    rep(i, q) {
      k[i] = tmp[i].first;
      perm[tmp[i].second] = i;
    }
  }

  int k_ans[40][40];
  rep(i, n) k_ans[i][0] = -1; // NA
  // k
  // テ」ツ?ョテ・ツーツ湘」ツ?陛」ツ??ゥツ??」ツ?ォテ・ツ?ヲテァツ青?」ツ?療」ツ?ヲテ」ツ??」ツ??
  // テ、ツクツ?・ツコツヲ NA
  // テ」ツ?ォテ」ツ?ェテ」ツ?」テ」ツ?淌」ツつ嘉」ツ?敕」ツつ古、ツサツ・テゥツ卍催」ツ?ッテ・ツ?ィテゥツδィ
  // NA
  rep(i, q) {
    K = k[i];

    ans = INF;
    rep(j, n) rep(k, n) if (j != k) { // fix an edge of the polygon
      Q[0] = P[j];
      Q[1] = P[k];
      rep(l, n) vis[l] = false;
      vis[j] = vis[k] = true;

      // pruning
      // テヲツ伉偲」ツつ嘉」ツ?凝」ツ?ォテ」ツδ?」ツδ。テ」ツ?ェテァツつケテ」ツ?ッテヲツ慊?・ツ按敕」ツ?凝」ツつ嘉ィツェツソテ」ツ?ケテ」ツ?ェテ」ツ??
      rep(l, n) if (ccw(Q[0], Q[1], P[l]) != CCW ||
                    ccw(P[l], Q[0], Q[1]) != CCW) vis[l] = true;

      ub = 0;
      dfs(2, 0);
    }

    if (ans > INF / 2)
      break; // NA

    int j0 = 0;
    vector<int> seq(K);
    rep(j, K) {
      seq[j] = find(P, P + n, Q_ans[j]) - P;
      if (make_pair(Q_ans[j].y, Q_ans[j].x) <
          make_pair(Q_ans[j0].y, Q_ans[j0].x))
        j0 = j;
    }
    rep(j, j0) {
      seq.push_back(seq[0]);
      seq.erase(seq.begin());
    }
    rep(j, K) k_ans[i][j] = seq[j];
  }

  rep(i, q) {
    int idx = perm[i];
    if (k_ans[idx][0] == -1)
      puts("NA");
    else {
      rep(j, k[idx])
          printf("%d%c", k_ans[idx][j] + 1, j < k[idx] - 1 ? ' ' : '\\n');
    }
  }

  return 0;
}

Error: TLE

Fixed submission:

#include <algorithm>
#include <cmath>
#include <cstdio>
#include <cstring>
#include <vector>

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

using namespace std;

const double EPS = 1e-8;
const double INF = 1e77;

struct point {
  double x, y;
  point() : x(0), y(0) {}
  point(double x, double y) : x(x), y(y) {}
  point operator-(const point &a) const { return point(x - a.x, y - a.y); }
  bool operator==(const point &a) const {
    return abs(x - a.x) < EPS && abs(y - a.y) < EPS;
  }
};

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

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

inline double area(const point &a, const point &b, const point &c) {
  return abs(cross(b - a, c - a)) / 2;
}

int n;
point P[40];

int K;
double ans;
point Q[40], Q_ans[40];
bool vis[40];

int ub;
void dfs(int i, double a) { // a: area of the polygon Q[0...i-1]
  ub++;
  if (ub > 100000)
    return; // テヲツ慊?ゥツ?ゥティツァツ」テ」ツ?凝」ツ?ゥテ」ツ??」ツ?凝」ツ?古ァツ「ツコテ、ツソツ。テ」ツ?ァテ」ツ?催」ツ?ェテ」ツ?湘」ツ?ヲテ」ツつづ・ツ債?・ツ按?」ツ?淌」ツ?湘」ツ?陛」ツつ禿ィツェツソテ」ツ?ケテ」ツ?淌」ツつ嘉ヲツ可禿」ツ?。テ・ツ按?」ツつ?..

  if (i == K) {
    if (a < ans) {
      ans = a;
      memcpy(Q_ans, Q, sizeof Q);
    }
    return;
  }

  // pruning
  // テ・ツ?凖ィツ」ツ愿ァツつケテ」ツ?ョテヲツ閉ーテ」ツ?古ィツカツウテ」ツつ甘」ツ?ェテ」ツ?湘」ツ?ェテ」ツ?」テ」ツ?淌」ツつ嘉ヲツ可禿」ツ?。テ・ツ按?」ツつ?
  int m = 0, next[40]; // next candidates
  rep(j, n) {
    if (!vis[j] && ccw(Q[i - 2], Q[i - 1], P[j]) == CCW &&
        ccw(Q[i - 1], P[j], Q[0]) == CCW)
      next[m++] = j;
  }
  if (m < K - i)
    return;

  // pruning
  // テゥツ敖「テァツゥツ催」ツ?古、ツサツ甘」ツ?セテ」ツ?ァテ」ツ?ョテヲツ慊?・ツーツ湘」ツつ津ィツカツ?」ツ?暗」ツ?淌」ツつ嘉ヲツ可禿」ツ?。テ・ツ按?」ツつ?
  double da = INF;
  rep(j, m) da = min(da, area(Q[i - 1], P[next[j]], Q[0]));
  if (ans < a + da + EPS)
    return;

  double res = INF;
  rep(j, m) {
    Q[i] = P[next[j]];
    vis[next[j]] = true;
    dfs(i + 1, a + area(Q[0], Q[i - 1], Q[i]));
    vis[next[j]] = false;
  }
}

int main() {
  scanf("%d", &n);
  rep(i, n) scanf("%lf%lf", &P[i].x, &P[i].y);

  int q;
  scanf("%d", &q);
  int k[40], perm[40];
  rep(i, q) scanf("%d", k + i);
  {
    pair<int, int> tmp[40];
    rep(i, q) tmp[i] = make_pair(k[i], i);
    sort(tmp, tmp + q);
    rep(i, q) {
      k[i] = tmp[i].first;
      perm[tmp[i].second] = i;
    }
  }

  int k_ans[40][40];
  rep(i, n) k_ans[i][0] = -1; // NA
  // k
  // テ」ツ?ョテ・ツーツ湘」ツ?陛」ツ??ゥツ??」ツ?ォテ・ツ?ヲテァツ青?」ツ?療」ツ?ヲテ」ツ??」ツ??
  // テ、ツクツ?・ツコツヲ NA
  // テ」ツ?ォテ」ツ?ェテ」ツ?」テ」ツ?淌」ツつ嘉」ツ?敕」ツつ古、ツサツ・テゥツ卍催」ツ?ッテ・ツ?ィテゥツδィ
  // NA
  rep(i, q) {
    K = k[i];

    ans = INF;
    rep(j, n) rep(k, n) if (j != k) { // fix an edge of the polygon
      Q[0] = P[j];
      Q[1] = P[k];
      rep(l, n) vis[l] = false;
      vis[j] = vis[k] = true;

      // pruning
      // テヲツ伉偲」ツつ嘉」ツ?凝」ツ?ォテ」ツδ?」ツδ。テ」ツ?ェテァツつケテ」ツ?ッテヲツ慊?・ツ按敕」ツ?凝」ツつ嘉ィツェツソテ」ツ?ケテ」ツ?ェテ」ツ??
      rep(l, n) if (ccw(Q[0], Q[1], P[l]) != CCW ||
                    ccw(P[l], Q[0], Q[1]) != CCW) vis[l] = true;

      ub = 0;
      dfs(2, 0);
    }

    if (ans > INF / 2)
      break; // NA

    int j0 = 0;
    vector<int> seq(K);
    rep(j, K) {
      seq[j] = find(P, P + n, Q_ans[j]) - P;
      if (make_pair(Q_ans[j].y, Q_ans[j].x) <
          make_pair(Q_ans[j0].y, Q_ans[j0].x))
        j0 = j;
    }
    rep(j, j0) {
      seq.push_back(seq[0]);
      seq.erase(seq.begin());
    }
    rep(j, K) k_ans[i][j] = seq[j];
  }

  rep(i, q) {
    int idx = perm[i];
    if (k_ans[idx][0] == -1)
      puts("NA");
    else {
      rep(j, k[idx])
          printf("%d%c", k_ans[idx][j] + 1, j < k[idx] - 1 ? ' ' : '\\n');
    }
  }

  return 0;
}