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

#include <algorithm>
#include <climits>
#include <cmath>
#include <iostream>
#include <vector>
using namespace std;

const int NIL = -1;
const int INF = INT_MAX;

struct Point {
  int id;
  int x, y;
  Point(int id, int x, int y) : id(id), x(x), y(y) {}
};
const Point operator-(const Point &lhs, const Point &rhs) {
  return Point(lhs.id, lhs.x - rhs.x, lhs.y - rhs.y);
}
bool operator<(const Point &lhs, const Point &rhs) {
  if (lhs.y != rhs.y)
    return lhs.y < rhs.y;
  if (lhs.x != rhs.x)
    return lhs.x < rhs.x;
  return lhs.id < rhs.id;
}
int cross(const Point &lhs, const Point &rhs) {
  return lhs.x * rhs.y - lhs.y * rhs.x;
}
int area(const Point &a, const Point &b, const Point &c) {
  return fabs(cross(b - a, c - a));
}
bool ccw(const Point &a, const Point &b, const Point &c) {
  return cross(b - a, c - a) > 0;
}
bool ccw(const vector<Point> &seq) {
  for (int i = 0; i < seq.size(); ++i)
    if (!ccw(seq[i], seq[(i + 1) % seq.size()], seq[(i + 2) % seq.size()]))
      return false;
  return true;
}
struct Compare {
  Point p;
  Compare(const Point &p) : p(p) {}
  bool operator()(const Point &lhs, const Point &rhs) const {
    return ccw(p, lhs, rhs);
  }
};

int main() {
  int N, Q;
  cin >> N;
  vector<Point> point;
  for (int i = 0; i < N; ++i) {
    int x, y;
    cin >> x >> y;
    point.push_back(Point(i, x, y));
  }
  cin >> Q;
  vector<int> query(Q);
  for (auto &q : query)
    cin >> q;

  vector<int> answer(N + 1, INF);
  vector<vector<int>> answer_sequence(N + 1);
  sort(point.begin(), point.end());
  for (int a = 0; a < N - 2; ++a) {
    vector<vector<vector<vector<int>>>> dp(
        N + 1, vector<vector<vector<int>>>(
                   N, vector<vector<int>>(N, vector<int>(N, INF))));
    vector<vector<vector<vector<int>>>> pre(
        N + 1, vector<vector<vector<int>>>(
                   N, vector<vector<int>>(N, vector<int>(N, NIL))));
    const Point &start = point[a];
    vector<Point> p(point.begin() + a + 1, point.end());
    sort(p.begin(), p.end(), Compare(start));
    for (int b = 0; b < p.size(); ++b)
      for (int c = b + 1; c < p.size(); ++c) {
        if (!ccw(start, p[b], p[c]))
          continue;
        int cost = area(start, p[b], p[c]);
        if (dp[3][p[b].id][p[b].id][p[c].id] <= cost)
          continue;
        dp[3][p[b].id][p[b].id][p[c].id] = cost;
        if (answer[3] <= cost)
          continue;
        answer[3] = cost;
        answer_sequence[3] = {start.id, p[b].id, p[c].id};
      }
    for (int k = 4; k <= N; ++k)
      for (int b = 0; b < p.size(); ++b)
        for (int c = b; c < p.size(); ++c)
          for (int d = c + 1; d < p.size(); ++d) {
            for (int i = d + 1; i < p.size(); ++i) {
              if (!ccw(p[i], start, p[b]))
                continue;
              if (!ccw(p[d], p[i], start))
                continue;
              if (!ccw(p[c], p[d], p[i]))
                continue;
              if (dp[k - 1][p[b].id][p[c].id][p[d].id] == INF)
                continue;
              int cost = dp[k - 1][p[b].id][p[c].id][p[d].id] +
                         area(p[d], start, p[i]);
              if (dp[k][p[b].id][p[d].id][p[i].id] <= cost)
                continue;
              dp[k][p[b].id][p[d].id][p[i].id] = cost;
              pre[k][p[b].id][p[d].id][p[i].id] = p[c].id;
              if (answer[k] <= cost)
                continue;
              answer[k] = cost;
              answer_sequence[k] = {start.id, p[d].id, p[i].id};
              int K = k;
              int B = p[b].id;
              int C = p[d].id;
              int D = p[i].id;
              while (pre[K][B][C][D] != NIL) {
                answer_sequence[k].insert(answer_sequence[k].begin() + 1,
                                          pre[K][B][C][D]);
                int t = D;
                D = C;
                C = pre[K][B][C][t];
                --K;
              }
            }
          }
  }

  for (const auto &q : query) {
    if (answer[q] == INF)
      cout << "NA" << endl;
    else {
      for (int i = 0; i < q; ++i)
        cout << (i ? " " : "") << answer_sequence[q][i] + 1;
      cout << endl;
    }
  }
}

Error: MLE

Fixed submission:

#include <algorithm>
#include <climits>
#include <cmath>
#include <iostream>
#include <vector>
using namespace std;

const int INF = INT_MAX;

struct Point {
  int id;
  int x, y;
  Point(int id, int x, int y) : id(id), x(x), y(y) {}
};
const Point operator-(const Point &lhs, const Point &rhs) {
  return Point(lhs.id, lhs.x - rhs.x, lhs.y - rhs.y);
}
bool operator<(const Point &lhs, const Point &rhs) {
  if (lhs.y != rhs.y)
    return lhs.y < rhs.y;
  if (lhs.x != rhs.x)
    return lhs.x < rhs.x;
  return lhs.id < rhs.id;
}
int cross(const Point &lhs, const Point &rhs) {
  return lhs.x * rhs.y - lhs.y * rhs.x;
}
int area(const Point &a, const Point &b, const Point &c) {
  return fabs(cross(b - a, c - a));
}
bool ccw(const Point &a, const Point &b, const Point &c) {
  return cross(b - a, c - a) > 0;
}
bool ccw(const vector<Point> &seq) {
  for (int i = 0; i < seq.size(); ++i)
    if (!ccw(seq[i], seq[(i + 1) % seq.size()], seq[(i + 2) % seq.size()]))
      return false;
  return true;
}
struct Polygon {
  int area;
  vector<Point> point;
  Polygon() : area(INF) {}
};
bool operator<(const Polygon &lhs, const Polygon &rhs) {
  return lhs.area < rhs.area;
}
struct Compare {
  Point p;
  Compare(const Point &p) : p(p) {}
  bool operator()(const Point &lhs, const Point &rhs) const {
    return ccw(p, lhs, rhs);
  }
};

int main() {
  int N, Q;
  cin >> N;
  vector<Point> p;
  for (int i = 0; i < N; ++i) {
    int x, y;
    cin >> x >> y;
    p.push_back(Point(i, x, y));
  }
  cin >> Q;
  vector<int> query(Q);
  for (auto &q : query)
    cin >> q;

  vector<Polygon> answer(N + 1);

  vector<vector<vector<vector<Polygon>>>> dp(
      N, vector<vector<vector<Polygon>>>(
             N + 1, vector<vector<Polygon>>(N, vector<Polygon>(N))));
  for (int a = 0; a < N; ++a)
    for (int b = 0; b < N; ++b)
      for (int c = 0; c < N; ++c) {
        if (!ccw(p[a], p[b], p[c]))
          continue;
        int cost = area(p[a], p[b], p[c]);
        if (dp[a][3][b][c].area <= cost)
          continue;
        dp[a][3][b][c].area = cost;
        dp[a][3][b][c].point = {p[a], p[b], p[c]};
        answer[3] = min(answer[3], dp[a][3][b][c]);
      }

  for (int a = 0; a < N; ++a) {
    for (int k = 4; k <= N; ++k)
      for (int b = 0; b < N; ++b)
        for (int c = 0; c < N; ++c) {
          if (!ccw(p[a], p[b], p[c]))
            continue;
          if (dp[a][k - 1][b][c].area == INF)
            continue;
          for (int d = 0; d < N; ++d) {
            int cost = dp[a][k - 1][b][c].area + area(p[c], p[d], p[a]);
            vector<Point> seq = dp[a][k - 1][b][c].point;
            seq.push_back(p[d]);
            if (dp[a][k][b][d].area <= cost)
              continue;
            if (!ccw(seq))
              continue;
            dp[a][k][b][d].area = cost;
            dp[a][k][b][d].point = seq;
            answer[k] = min(answer[k], dp[a][k][b][d]);
          }
        }
  }

  for (const auto &q : query) {
    if (answer[q].area == INF)
      cout << "NA" << endl;
    else {
      vector<Point> t = answer[q].point;
      sort(t.begin(), t.end());
      sort(t.begin() + 1, t.end(), Compare(t.front()));
      for (int i = 0; i < q; ++i)
        cout << (i ? " " : "") << t[i].id + 1;
      cout << endl;
    }
  }
}