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

#include <iostream>
#include <queue>
#include <vector>

using namespace std;

struct State {
  vector<int> S[3];
  int step;
  int parent_from;
  int parent_to;

  bool empty(size_t i) const { return S[i].size() == 0; }
  void push(size_t i, int v) { S[i].push_back(v); }
  void pop(size_t i) { S[i].pop_back(); }
  int top(size_t i) const { return S[i].back(); }
};

inline bool IsMovable(int from, int to, const State &p) {
  if (to < 0 || to >= 3)
    return false;
  if (p.empty(from))
    return false;
  if (to == p.parent_from && from == p.parent_to)
    return false;
  return p.empty(to) || p.top(from) >= p.top(to);
}

inline bool Done(int n, const State &p) {
  return p.S[0].size() == n || p.S[2].size() == n;
}

int BFS(const State &start, int n) {
  queue<State> q;
  q.push(start);

  int step = 0;
  while (!q.empty()) {
    const auto p = q.front();
    q.pop();

    if (Done(n, p)) {
      step = p.step;
      break;
    }
    for (int from = 0; from < 3; ++from) {
      for (int d : {-1, 1}) {
        const int to = from + d;
        if (IsMovable(from, to, p)) {
          State new_state = p;
          new_state.step = p.step + 1;
          new_state.parent_from = from;
          new_state.parent_to = to;
          new_state.push(to, p.top(from));
          new_state.pop(from);
          q.push(new_state);
        }
      }
    }
  }
  return step;
}

int main() {
  cin.tie(0);
  ios::sync_with_stdio(false);

  int n, m;
  for (;;) {
    cin >> n >> m;
    if (n == 0 && m == 0)
      break;

    // State goal;
    State start;
    start.step = 0;
    for (int i = 0; i < 3; ++i) {
      int t;
      cin >> t;
      int k;
      for (int j = 0; j < t; ++j) {
        cin >> k;
        start.S[i].push_back(k);
      }
    }
    const auto step = BFS(start, n);
    const auto ans = step <= m ? step : -1;
    cout << ans << endl;
  }
  return 0;
}


Error: TLE

Fixed submission:

#include <cmath>
#include <iostream>
#include <queue>
#include <unordered_set>
#include <vector>

using namespace std;

struct State {
  vector<int> S[3];
  int step;

  bool empty(size_t i) const { return S[i].size() == 0; }
  void push(size_t i, int v) { S[i].push_back(v); }
  void pop(size_t i) { S[i].pop_back(); }
  int top(size_t i) const { return S[i].back(); }
};

struct StateHash {
  size_t operator()(const State &s) const {
    size_t h = 0;
    for (int i = 0; i < 3; ++i) {
      for (size_t j = 0; j < s.S[i].size(); ++j) {
        h += j * 10 * s.S[i][j];
      }
    }
    return h;
  }
};

inline bool operator==(const State &a, const State &b) {
  return a.S[0] == b.S[0] && a.S[1] == b.S[1] && a.S[2] == b.S[2];
}
inline bool operator!=(const State &a, const State &b) { return !(a == b); }

int BFS(const State &start, const State &goal) {
  unordered_set<State, StateHash> visited;
  queue<State> q;
  q.push(start);

  auto IsMovable = [&](int from, int to, const auto &p) {
    if (to < 0 || to >= 3)
      return false;
    return p.empty(to) || p.top(from) >= p.top(to);
  };

  int step = 0;
  while (!q.empty()) {
    const auto p = q.front();
    q.pop();

    if (p == goal) {
      step = p.step;
      break;
    }
    for (int from = 0; from < 3; ++from) {
      if (p.S[from].size() == 0)
        continue;
      for (int d : {-1, 1}) {
        const int to = from + d;
        if (IsMovable(from, to, p)) {
          State new_state = p;
          new_state.step = p.step + 1;
          new_state.push(to, p.top(from));
          new_state.pop(from);
          const auto it = visited.find(new_state);
          if (it == visited.end()) {
            visited.insert(new_state);
            q.push(new_state);
          }
        }
      }
    }
  }
  return step;
}

int main() {
  cin.tie(0);
  ios::sync_with_stdio(false);

  int n, m;
  for (;;) {
    cin >> n >> m;
    if (n == 0 && m == 0)
      break;

    State goal;
    for (int i = 0; i < 3; ++i) {
      int t;
      cin >> t;
      int k;
      for (int j = 0; j < t; ++j) {
        cin >> k;
        goal.S[i].push_back(k);
      }
    }
    State start;
    start.step = 0;
    for (int i = 1; i <= n; ++i) {
      start.S[2].push_back(i);
    }

    const int N = pow(3, n) - 1;
    const int step = BFS(start, goal);
    const int ans = N - step <= m ? N - step : -1;
    cout << ans << endl;
  }
  return 0;
}