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

#include <algorithm>
#include <cassert>
#include <iostream>
#include <queue>
#include <vector>
#define NUM 8
#define MAX 40320

using namespace std;

struct Board {
  int key;
  int num[NUM];
  int pos[NUM];
  int depth;
  bool vis;
  void print() const {
    cout << num[0];
    for (int i = 1; i < NUM; ++i)
      cout << ' ' << num[i];
    cout << '\\n';
  }
  bool check() const {
    for (int i = 0; i < NUM; ++i)
      if (num[i] != i)
        return false;
    return true;
  }
  void refreshKey() {
    key = num[0] + 1;
    for (int i = 1; i < NUM; ++i) {
      key *= 10;
      key += num[i] + 1;
    }
  }
  bool operator<(const Board &b) const { return key < b.key; }
};

Board M[MAX];
int sz;

void ClearMap(void) {
  for (int i = 0; i < sizeof(M) / sizeof(*M); ++i) {
    M[i].vis = false;
    M[i].depth = 0;
  }
}
void PERM(int p[], int n) {
  int *c, *pc, *q, k, t;

  c = new int[n];
  for (k = 1, q = p, pc = c; k <= n;)
    *q++ = *pc++ = k++;
  k = 1;
  pc = c;
  do {
    t = *(p + k);
    *(p + k) = *(q = p + ((k & 1) ? *pc : 0));
    *q = t;

    for (int i = 0; i < NUM; ++i) {
      M[sz].num[i] = p[i] - 1;
      M[sz].pos[p[i] - 1] = i;
    }
    M[sz].refreshKey();
    M[sz].vis = false;
    M[sz].depth = 0;
    sz++;

    k = 1;
    pc = c;
    while (*pc == 0)
      *pc++ = k++;
    (*pc)--;
  } while (k < n);
  delete[] c;
}
int BinDet(const Board &b) {
  int l = 0, r = MAX, m = r;

  if (b.key == M[l].key)
    return l;
  if (b.key == M[r - 1].key)
    return r - 1;

  while (r - 1 > l) {
    m = (l + r) / 2;
    if (b.key > M[m].key)
      l = m;
    else if (b.key < M[m].key)
      r = m;
    else
      break;
  }
  return m;
}
inline void SubNext(Board &bd, int from, int to) {
  swap(bd.pos[bd.num[from]], bd.pos[bd.num[to]]);
  swap(bd.num[from], bd.num[to]);
}
void Next(const Board &b, vector<int> &vNext) {
  Board bt[3];
  int dp[NUM][3] = {{1, 4, -1}, {0, 2, 5}, {1, 3, 6}, {2, 7, -1},
                    {0, 5, -1}, {1, 4, 6}, {2, 5, 7}, {3, 6, -1}};
  int x;

  for (int i = 0; i < 3; ++i) {
    bt[i] = b;
  }
  x = b.pos[0];

  for (int i = 0; i < 3; ++i) {
    if (dp[x][i] >= 0) {
      int pos;

      SubNext(bt[i], x, dp[x][i]);
      bt[i].refreshKey();
      pos = BinDet(bt[i]);

      assert(M[pos].key == bt[i].key);

      vNext.push_back(pos);
    }
  }
}

void BFS(int s) {
  queue<int> q;

  q.push(s);

  while (!q.empty()) {
    int n = q.front();
    vector<int> next;
    q.pop();

    if (M[n].vis)
      continue;
    else
      M[n].vis = true;

    Next(M[n], next);
    for (unsigned int i = 0; i < next.size(); ++i) {
      if (!M[next[i]].vis) {
        M[next[i]].depth = M[n].depth + 1;
        q.push(next[i]);
      }
    }
  }
}
int main(void) {
  int p[NUM];
  // cout << "INITIALIZE...\\n";
  PERM(p, NUM);
  // cout << "PERM END\\n";
  sort(M, M + sizeof(M) / sizeof(*M));
  // cout << "SORT END\\n";
  BFS(0);
  // cout << "BFS END\\n";
  while (true) {
    Board bst;

    // cout << "DATASET: \\n";
    for (int i = 0; i < NUM; ++i) {
      int t;

      cin >> t;
      if (cin.eof())
        return 0;
      bst.num[i] = t;
      bst.pos[t] = i;
    }
    bst.refreshKey();
    int pos = BinDet(bst);
    cout << M[pos].depth << '\\n';
  }
  return 0;
}

Error: TLE

Fixed submission:

#include <algorithm>
#include <cassert>
#include <iostream>
#include <queue>
#include <vector>
#define NUM 8
#define MAX 40320

using namespace std;

struct Board {
  int key;
  int num[NUM];
  int pos[NUM];
  int depth;
  bool vis;
  void print() const {
    cout << num[0];
    for (int i = 1; i < NUM; ++i)
      cout << ' ' << num[i];
    cout << '\\n';
  }
  bool check() const {
    for (int i = 0; i < NUM; ++i)
      if (num[i] != i)
        return false;
    return true;
  }
  void refreshKey() {
    key = num[0] + 1;
    for (int i = 1; i < NUM; ++i) {
      key *= 10;
      key += num[i] + 1;
    }
  }
  bool operator<(const Board &b) const { return key < b.key; }
};

Board M[MAX];
int sz;

void ClearMap(void) {
  for (int i = 0; i < sizeof(M) / sizeof(*M); ++i) {
    M[i].vis = false;
    M[i].depth = 0;
  }
}
void PERM(int p[], int n) {
  int *c, *pc, *q, k, t;

  c = new int[n];
  for (k = 1, q = p, pc = c; k <= n;)
    *q++ = *pc++ = k++;
  k = 1;
  pc = c;
  do {
    t = *(p + k);
    *(p + k) = *(q = p + ((k & 1) ? *pc : 0));
    *q = t;

    for (int i = 0; i < NUM; ++i) {
      M[sz].num[i] = p[i] - 1;
      M[sz].pos[p[i] - 1] = i;
    }
    M[sz].refreshKey();
    M[sz].vis = false;
    M[sz].depth = 0;
    sz++;

    k = 1;
    pc = c;
    while (*pc == 0)
      *pc++ = k++;
    (*pc)--;
  } while (k < n);
  delete[] c;
}
int BinDet(const Board &b) {
  int l = 0, r = MAX, m = r;

  if (b.key == M[l].key)
    return l;
  if (b.key == M[r - 1].key)
    return r - 1;

  while (r - 1 > l) {
    m = (l + r) / 2;
    if (b.key > M[m].key)
      l = m;
    else if (b.key < M[m].key)
      r = m;
    else
      break;
  }
  return m;
}
inline void SubNext(Board &bd, int from, int to) {
  swap(bd.pos[bd.num[from]], bd.pos[bd.num[to]]);
  swap(bd.num[from], bd.num[to]);
}
void Next(const Board &b, vector<int> &vNext) {
  Board bt[3];
  int dp[NUM][3] = {{1, 4, -1}, {0, 2, 5}, {1, 3, 6}, {2, 7, -1},
                    {0, 5, -1}, {1, 4, 6}, {2, 5, 7}, {3, 6, -1}};
  int x;

  for (int i = 0; i < 3; ++i) {
    bt[i] = b;
  }
  x = b.pos[0];

  for (int i = 0; i < 3; ++i) {
    if (dp[x][i] >= 0) {
      int pos;

      SubNext(bt[i], x, dp[x][i]);
      bt[i].refreshKey();
      pos = BinDet(bt[i]);

      assert(M[pos].key == bt[i].key);

      M[pos].depth = b.depth + 1;
      vNext.push_back(pos);
    }
  }
}

void BFS(int s) {
  queue<int> q;

  q.push(s);

  while (!q.empty()) {
    int n = q.front();
    vector<int> next;
    q.pop();

    if (M[n].vis)
      continue;
    else
      M[n].vis = true;

    Next(M[n], next);
    for (unsigned int i = 0; i < next.size(); ++i)
      if (!M[next[i]].vis)
        q.push(next[i]);
  }
}
int main(void) {
  int p[NUM];
  cout << "INITIALIZE...\\n";
  PERM(p, NUM);
  cout << "PERM END\\n";
  sort(M, M + sizeof(M) / sizeof(*M));
  cout << "SORT END\\n";
  while (true) {
    Board bst;

    for (int i = 0; i < NUM; ++i) {
      int t;

      cin >> t;
      if (cin.eof())
        return 0;
      bst.num[i] = t;
      bst.pos[t] = i;
    }
    bst.refreshKey();
    int pos = BinDet(bst);
    ClearMap();
    BFS(pos);
    cout << M[0].depth << '\\n';
  }
  return 0;
}