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

#include <iostream>
#include <stack>
#include <vector>

using namespace std;

int main_calc(int n, int m, stack<int> **tray);

int main(int argc, char const *argv[]) {
  int n, m;
  int size;
  int val;
  stack<int> *tray[3];

  while (true) {
    cin >> n >> m;
    if (n == 0 && m == 0)
      break;

    for (int i = 0; i < 3; i++) {
      cin >> size;
      tray[i] = new stack<int>;

      for (int j = 0; j < size; j++) {
        cin >> val;
        tray[i]->push(val);
      }
    }

    cout << main_calc(n, m, tray) << endl;
  }

  cin >> n >> m;
  return 0;
}

enum Move { AB, BA, BC, CB, NO };

void move(stack<int> **tray, Move move) {
  int tray_0 = tray[0]->size() == 0 ? 0 : tray[0]->top();
  int tray_1 = tray[1]->size() == 0 ? 0 : tray[1]->top();
  int tray_2 = tray[2]->size() == 0 ? 0 : tray[2]->top();

  switch (move) {
  case AB:
    tray[1]->push(tray_0);
    if (tray[0]->size() > 0)
      tray[0]->pop();
    break;
  case BA:
    tray[0]->push(tray_1);
    if (tray[1]->size() > 0)
      tray[1]->pop();
    break;
  case BC:
    tray[2]->push(tray_1);
    if (tray[1]->size() > 0)
      tray[1]->pop();
    break;
  case CB:
    tray[1]->push(tray_2);
    if (tray[2]->size() > 0)
      tray[2]->pop();
    break;
  case NO:
    break;
  }
}

vector<Move> *get_movables(stack<int> **tray, Move lastmove) {
  auto moves = new vector<Move>;
  int tray_0 = tray[0]->size() == 0 ? 0 : tray[0]->top();
  int tray_1 = tray[1]->size() == 0 ? 0 : tray[1]->top();
  int tray_2 = tray[2]->size() == 0 ? 0 : tray[2]->top();

  // AB
  if (tray_0 > tray_1 && lastmove != BA) {
    moves->push_back(AB);
  }

  // BA
  if (tray_1 > tray_0 && lastmove != AB) {
    moves->push_back(BA);
  }

  // BC
  if (tray_1 > tray_2 && lastmove != CB) {
    moves->push_back(BC);
  }

  // CB
  if (tray_2 > tray_1 && lastmove != BC) {
    moves->push_back(CB);
  }

  return moves;
}

stack<int> **copy(stack<int> **tray) {
  auto **new_tray = new stack<int> *[3];
  new_tray[0] = new stack<int>(*tray[0]);
  new_tray[1] = new stack<int>(*tray[1]);
  new_tray[2] = new stack<int>(*tray[2]);
  return new_tray;
}

void debugout(stack<int> **tray) {
  int tray_0 = tray[0]->size() == 0 ? 0 : tray[0]->top();
  int tray_1 = tray[1]->size() == 0 ? 0 : tray[1]->top();
  int tray_2 = tray[2]->size() == 0 ? 0 : tray[2]->top();

  cout << tray_0 << " " << tray_1 << " " << tray_2 << endl;
}

int single_calc(int m, stack<int> **tray, Move first_move = NO) {
  int count = 0;
  auto *moves = get_movables(tray, first_move);

  while (true) {
    // cout << count << ": " << moves->size() << endl;
    // debugout(tray);
    if (tray[1]->empty() && (tray[0]->empty() || tray[2]->empty())) {
      // cout << "end" << endl;
      break;
    }

    Move recent = (*moves)[0];
    delete moves;

    if (count == m || moves->size() == 0) {
      return -1;
    }

    move(tray, recent);
    moves = get_movables(tray, recent);
    count++;
  }

  return count;
}

int main_calc(int n, int m, stack<int> **tray) {
  if (tray[1]->empty() && (tray[0]->empty() || tray[1]->empty()))
    return 0;

  int count = 0, min = m + 1;
  auto *moves = get_movables(tray, NO);

  if (moves->size() == 0)
    return -1;

  for (auto &move_type : *moves) {
    auto copy_tray = copy(tray);
    move(copy_tray, move_type);
    count = single_calc(m - 1, copy_tray, move_type);

    if (count != -1 && count + 1 < min)
      min = count + 1;
  }

  if (min == m + 1) {
    return -1;
  }

  return min;
}

Error: MLE

Fixed submission:

#include <iostream>
#include <stack>
#include <vector>

using namespace std;

int main_calc(int n, int m, stack<int> **tray);

int main(int argc, char const *argv[]) {
  int n, m;
  int size;
  int val;
  stack<int> *tray[3];

  while (true) {
    cin >> n >> m;
    if (n == 0 && m == 0)
      break;

    for (int i = 0; i < 3; i++) {
      cin >> size;
      tray[i] = new stack<int>;

      for (int j = 0; j < size; j++) {
        cin >> val;
        tray[i]->push(val);
      }
    }

    cout << main_calc(n, m, tray) << endl;
  }

  cin >> n >> m;
  return 0;
}

enum Move { AB, BA, BC, CB, NO };

void move(stack<int> **tray, Move move) {
  int tray_0 = tray[0]->size() == 0 ? 0 : tray[0]->top();
  int tray_1 = tray[1]->size() == 0 ? 0 : tray[1]->top();
  int tray_2 = tray[2]->size() == 0 ? 0 : tray[2]->top();

  switch (move) {
  case AB:
    tray[1]->push(tray_0);
    if (tray[0]->size() > 0)
      tray[0]->pop();
    break;
  case BA:
    tray[0]->push(tray_1);
    if (tray[1]->size() > 0)
      tray[1]->pop();
    break;
  case BC:
    tray[2]->push(tray_1);
    if (tray[1]->size() > 0)
      tray[1]->pop();
    break;
  case CB:
    tray[1]->push(tray_2);
    if (tray[2]->size() > 0)
      tray[2]->pop();
    break;
  case NO:
    break;
  }
}

vector<Move> *get_movables(stack<int> **tray, Move lastmove) {
  auto moves = new vector<Move>;
  int tray_0 = tray[0]->size() == 0 ? 0 : tray[0]->top();
  int tray_1 = tray[1]->size() == 0 ? 0 : tray[1]->top();
  int tray_2 = tray[2]->size() == 0 ? 0 : tray[2]->top();

  // AB
  if (tray_0 > tray_1 && lastmove != BA) {
    moves->push_back(AB);
  }

  // BA
  if (tray_1 > tray_0 && lastmove != AB) {
    moves->push_back(BA);
  }

  // BC
  if (tray_1 > tray_2 && lastmove != CB) {
    moves->push_back(BC);
  }

  // CB
  if (tray_2 > tray_1 && lastmove != BC) {
    moves->push_back(CB);
  }

  return moves;
}

stack<int> **copy(stack<int> **tray) {
  auto **new_tray = new stack<int> *[3];
  new_tray[0] = new stack<int>(*tray[0]);
  new_tray[1] = new stack<int>(*tray[1]);
  new_tray[2] = new stack<int>(*tray[2]);
  return new_tray;
}

void debugout(stack<int> **tray) {
  int tray_0 = tray[0]->size() == 0 ? 0 : tray[0]->top();
  int tray_1 = tray[1]->size() == 0 ? 0 : tray[1]->top();
  int tray_2 = tray[2]->size() == 0 ? 0 : tray[2]->top();

  cout << tray_0 << " " << tray_1 << " " << tray_2 << endl;
}

int single_calc(int m, stack<int> **tray, Move first_move = NO) {
  int count = 0;
  auto *moves = get_movables(tray, first_move);

  while (true) {
    // cout << count << ": " << moves->size() << endl;
    // debugout(tray);
    if (tray[1]->empty() && (tray[0]->empty() || tray[2]->empty())) {
      // cout << "end" << endl;
      break;
    }

    move(tray, (*moves)[0]);
    moves = get_movables(tray, (*moves)[0]);
    count++;

    if (count == m || moves->size() == 0) {
      return -1;
    }
  }

  return count;
}

int main_calc(int n, int m, stack<int> **tray) {
  if (tray[1]->empty() && (tray[0]->empty() || tray[1]->empty()))
    return 0;

  int count = 0, min = m + 1;
  auto *moves = get_movables(tray, NO);

  if (moves->size() == 0)
    return -1;

  for (auto &move_type : *moves) {
    auto copy_tray = copy(tray);
    move(copy_tray, move_type);
    count = single_calc(m - 1, copy_tray, move_type);

    if (count != -1 && count + 1 < min)
      min = count + 1;
  }

  if (min == m + 1) {
    return -1;
  }

  return min;
}