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

#include <cmath>
#include <cstdlib>
#include <iostream>
#define f(n) ((int)pow(3.0, n) - 1)
int A, N, M, S[16];
int v(int n, int m, int g) {
  if (m <= N)
    return v(n - 1, m + 1, S[m] == 1 ? g + 2 * (1 - g) : g) +
           abs(g - S[m]) * (f(n - 1) + 1);
  else
    return 0;
}
int main() {
  while (1) {
    scanf("%d%d", &N, &M);
    if (!(N || M))
      break;
    for (int i = 0; i < 3; ++i) {
      int t;
      scanf("%d", &t);
      for (int j = 0; j < t; ++j) {
        int u;
        scanf("%d", &u);
        S[u] = i;
      }
    }
    A = v(N, 1, 0);
    A = std::min(A, f(N) - A);
    A = A <= M ? A : -1;
    printf("%d\\n", A);
  }
  return 0;
}

Error: MLE

Fixed submission:

#include <algorithm>
#include <bitset>
#include <cstdio>
#include <cstdlib>
#include <iostream>
#include <queue>
#include <set>

#define MAX 16
#define A 0
#define B 1
#define C 2
#define P_MAX 3
#define M_MAX 16000000

using namespace std;

struct Cups {
  Cups() {
    cost = 0;
    v[0].reserve(MAX);
    v[1].reserve(MAX);
    v[2].reserve(MAX);
  }
  bitset<MAX> key[P_MAX];
  vector<int> v[P_MAX];
  bool operator<(const Cups &t) const {
    unsigned long l0 = key[0].to_ulong(), tl0 = t.key[0].to_ulong();
    unsigned long l1 = key[1].to_ulong(), tl1 = t.key[1].to_ulong();
    unsigned long l2 = key[2].to_ulong(), tl2 = t.key[2].to_ulong();

    if (l0 < tl0) {
      return true;
    } else if (l0 == tl0 && l1 < tl1) {
      return true;
    } else if (l0 == tl0 && l1 == tl1 && l2 < tl2) {
      return true;
    } else if (l0 == tl0 && l1 == tl1 && l2 == tl2 && cost < t.cost)
      return true;

    return false;
  }
  bool operator==(const Cups &t) const {
    return key[0].to_ulong() == t.key[0].to_ulong() &&
           key[1].to_ulong() == t.key[1].to_ulong() &&
           key[2].to_ulong() == t.key[2].to_ulong() && cost <= t.cost;
  }
  void CalcKey() {
    for (int i = 0; i < P_MAX; ++i) {
      key[i] = 0;
      for (unsigned int j = 0; j < v[i].size(); ++j) {
        key[i].set(v[i][j]);
      }
    }
  }
  int cost;
};
ostream &operator<<(ostream &os, const vector<int> &v) {
  for (unsigned int i = 0; i < v.size(); ++i) {
    os << v[i] << ' ';
  }
  return os;
}
ostream &operator<<(ostream &os, const Cups &t) {
  os << "A: " << t.v[0] << "\\t\\tB: " << t.v[1] << "\\t\\tC: " << t.v[2]
     << "\\t\\tCost :" << t.cost;
  return os;
}
int cost[3][MAX];

int BFS(int n, int m, int greedy, Cups &st) {
  int ret = M_MAX;
  set<Cups> vis_set;
  queue<Cups> q;

  st.CalcKey();
  vis_set.insert(st);
  q.push(st);
  while (!q.empty()) {
    Cups cups;
    cups = q.front();

    q.pop();

    /* I¹ð */
    if (cups.v[A].size() == n || cups.v[C].size() == n) {
      ret = min(ret, cups.cost);
      continue;
    }

    for (int i = A; i <= C; ++i) {
      int mov_cnt = 1;
      int min_sz = -1;

      for (int j = cups.v[i].size() - 1; j >= 1; --j) {
        if (cups.v[i][j] - cups.v[i][j - 1] == 1) {
          ++mov_cnt;
          min_sz = cups.v[i][j - 1];
        } else {
          min_sz = cups.v[i][j];
          break;
        }
      }
      if (cups.v[i].size() == 1)
        min_sz = cups.v[i][0];

      if (min_sz == -1)
        continue;

      for (int w = 1; w <= mov_cnt; ++w) {
        for (int j = A; j <= C; ++j) {
          int d = abs(i - j);
          if (d == 2 || d == 0)
            continue;

          Cups t = cups;
          int end = t.v[j].size() - 1;
          if (end >= 0 && t.v[j][end] > min_sz)
            break;

          t.v[j].insert(t.v[j].end(), t.v[i].end() - w, t.v[i].end());
          t.v[i].erase(t.v[i].end() - w, t.v[i].end());
          t.cost += cost[1][w];

          // cout << t;

          t.CalcKey();
          if (t.cost <= m && t.cost < ret && t.cost <= greedy &&
              vis_set.find(t) == vis_set.end()) {
            q.push(t);
            vis_set.insert(t);
            // cout << " ACCEPTED\\n";
          } // else
            // cout << " REJECTED\\n";
        }
      }
    }
  }
  return ret;
}
int Greedy(int n, const Cups &cups) {
  int ret = 0;
  int places[MAX];
  for (int i = 0; i < 3; ++i) {
    for (unsigned int j = 0; j < cups.v[i].size(); ++j) {
      places[cups.v[i][j]] = i;
    }
  }
  for (int i = n; i >= 2; --i) {
    int d = abs(places[i] - places[i - 1]);
    ret += cost[d][n - i + 1];
  }
  if (places[1] == B)
    ret += cost[1][n];

  return ret;
}
int main() {
  cost[1][1] = 1;
  cost[2][1] = 2;
  for (int i = 1; i < 3; ++i) {
    for (int j = 2; j < MAX; ++j) {
      if (i == 1) {
        cost[i][j] = 3 * cost[i][j - 1] + 1;
      } else {
        cost[i][j] = 2 * cost[1][j];
      }
    }
  }

  while (true) {
    int n, m;
    int greedy;
    int ans = 0;
    Cups cups;

    scanf("%d%d", &n, &m);
    if (n == 0 && m == 0)
      break;

    for (int i = 0; i < 3; ++i) {
      int t;
      scanf("%d", &t);
      for (int j = 0; j < t; ++j) {
        int tt;
        scanf("%d", &tt);
        cups.v[i].push_back(tt);
      }
    }
    greedy = Greedy(n, cups);
    ans = BFS(n, m, greedy, cups);

    printf("%d\\n", ans <= m ? ans : -1);
  }
  return 0;
}