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

#include <cassert>
#include <iostream>
#include <vector>

using namespace std;

int pow_(int a, int x) {
  int val = 1;
  for (int i = 0; i < x; ++i)
    val *= a;
  return val;
}

int main() {
  while (true) {
    int N, M;
    cin >> N >> M;
    if (!N && !M)
      break;

    vector<vector<int>> goal(3);
    for (int i = 0; i < 3; ++i) {
      int n;
      cin >> n;
      while (n--) {
        int idx;
        cin >> idx;
        goal[i].push_back(idx - 1);
      }
    }

    vector<vector<int>> field(3);
    for (int i = 0; i < N; ++i) {
      field[0].push_back(i);
    }

    int turn = 0;
    int prev_from = -1;
    int prev_to = -1;
    while (true) {
      if (field == goal) {
        break;
      }
      ++turn;
      for (int from = 0; from < 3; ++from) {
        if (field[from].size() == 0)
          continue;
        const int glass = field[from].back();
        const int to_1 = from - 1;
        const int to_2 = from + 1;
        if (!(from == prev_to && to_1 == prev_from) && to_1 >= 0 &&
            (field[to_1].size() == 0 || field[to_1].back() < glass)) {
          field[to_1].push_back(glass);
          field[from].pop_back();
          prev_from = from;
          prev_to = to_1;
          break;
        } else if (!(from == prev_to && to_2 == prev_from) && to_2 < 3 &&
                   (field[to_2].size() == 0 || field[to_2].back() < glass)) {
          field[to_2].push_back(glass);
          field[from].pop_back();
          prev_from = from;
          prev_to = to_2;
          break;
        } else {
        }
      }
    }
    const int MAXTURN = pow_(3, N) - 1;
    turn = min(turn, MAXTURN - turn);
    if (turn > M)
      turn = -1;
    cout << turn << endl;
  }
  return 0;
}

Error: MLE

Fixed submission:

#include <iostream>
#include <queue>
#include <tr1/unordered_set>
#include <utility>
#include <vector>

using namespace std;

const int DELTA[] = {-1, 1};

struct Hash {
  size_t operator()(const vector<int> &v) const {
    size_t val = 0;
    for (vector<int>::const_iterator it = v.begin(); it != v.end(); ++it) {
      val <<= 2;
      val += *it;
    }
    return val;
  }
};

bool all_a(const vector<int> &v, int val) {
  for (vector<int>::const_iterator it = v.begin(); it != v.end(); ++it) {
    if (*it != val)
      return false;
  }
  return true;
}

int main() {
  while (true) {
    int N, M;
    cin >> N >> M;
    if (!N && !M)
      break;

    vector<int> state(N);
    for (int i = 0; i < 3; ++i) {
      int n;
      cin >> n;
      while (n--) {
        int idx;
        cin >> idx;
        state[idx - 1] = i;
      }
    }

    tr1::unordered_set<vector<int>, Hash> visited;
    queue<pair<int, vector<int>>> q;
    q.push(make_pair(0, state));
    visited.insert(state);
    int ans = -1;
    while (!q.empty()) {
      int turn = q.front().first;
      vector<int> cur = q.front().second;
      /*
      cout << "(" << turn << ") ";
      for(int i = 0; i < cur.size(); ++i) {
          cout << cur[i] << ' ';
      }
      cout << endl;
      */
      q.pop();
      if (all_a(cur, 0) || all_a(cur, 2)) {
        ans = turn;
        break;
      }
      if (turn == M)
        continue;

      int top_of[3] = {-1, -1, -1};
      for (int i = N - 1; i >= 0; --i) {
        const int pos = cur[i];
        if (top_of[pos] == -1) {
          top_of[pos] = i;
          for (int j = 0; j < 2; ++j) {
            const int to = pos + DELTA[j];
            if (to < 0 || to >= 3)
              continue;
            if (top_of[to] < i) {
              vector<int> next = cur;
              next[i] = to;
              if (visited.count(next))
                continue;
              /*
              cout << "yield ";
              for(int k = 0; k < cur.size(); ++k) {
                  cout << next[k] << ' ';
              }
              cout << endl;
              */
              visited.insert(next);
              q.push(make_pair(turn + 1, next));
            }
          }
        }
      }
    }

    cout << ans << endl;
  }
  return 0;
}