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

#include <bits/stdc++.h>
#define rep(i, n) for (int i = 0; i < (int)(n); i++)
#define fs first
#define sc second
using namespace std;
typedef pair<int, int> pii;
typedef vector<int> vi;

const int dy[] = {-1, 0, 1, 0, 0}, dx[] = {0, 1, 0, -1, 0};

inline int encode(const vi &x, const int &w) {
  int res = 0, k = 1;
  for (int p : x) {
    res += k * p;
    k <<= 8;
  }
  return res;
}

inline vi decode(int x, const int &n, const int &w) {
  int k = 1 << 8;
  vi res(n);
  rep(i, n) {
    res[i] = x & (k - 1);
    x >>= 8;
  }
  return res;
}

short memo[1 << 24];

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

  int h, w, n;
  string g[16];
  while (cin >> w >> h >> n, w) {
    cin.ignore();

    vi start(n), end(n);
    rep(i, h) {
      getline(cin, g[i]);
      rep(j, w) {
        if (islower(g[i][j]))
          start[g[i][j] - 'a'] = i * w + j;
        if (isupper(g[i][j]))
          end[g[i][j] - 'A'] = i * w + j;
      }
    }
    int start_id = encode(start, w);
    int end_id = encode(end, w);

    vector<int> edge[256];
    rep(i, h) rep(j, w) {
      if (g[i][j] == '#')
        continue;
      rep(d, 5) {
        int ny = i + dy[d], nx = j + dx[d];
        if (g[ny][nx] != '#')
          edge[i * w + j].push_back(ny * w + nx);
      }
    }

    memset(memo, -1, sizeof(memo));
    memo[start_id] = 0;
    queue<int> q;
    q.push(start_id);

    while (q.size()) {
      int cur_id = q.front();
      q.pop();
      vi cur = decode(cur_id, n, w), nxt(n);
      if (cur_id == end_id)
        break;

      vi dir(n, 0);
      dir[0] = 0;
      while (dir[n - 1] < (int)edge[cur[n - 1]].size()) {
        bool f = true;
        rep(i, n) nxt[i] = edge[cur[i]][dir[i]];
        int nxt_id = encode(nxt, w);

        if (memo[nxt_id] == -2)
          f = false;
        else {
          for (int i = 0; f && i < n; i++) {
            for (int j = 0; f && j < i; j++) {
              if (nxt[i] == nxt[j])
                f = false;
            }
          }
        }

        if (!f)
          memo[nxt_id] = -2;
        else {
          for (int i = 0; f && i < n; i++) {
            for (int j = 0; f && j < i; j++) {
              if (nxt[i] == cur[j] && nxt[j] == cur[i])
                f = false;
            }
          }
        }

        if (f) {
          if (memo[nxt_id] < 0) {
            memo[nxt_id] = memo[cur_id] + 1;
            q.push(nxt_id);
          }
        }

        dir[0]++;
        for (int i = 0; i < n - 1; i++) {
          if (dir[i] == (int)edge[cur[i]].size())
            dir[i] = 0, dir[i + 1]++;
        }
      }
    }
    cout << memo[end_id] << endl;
  }
}

Error: TLE

Fixed submission:

#include <bits/stdc++.h>
#define rep(i, n) for (int i = 0; i < (int)(n); i++)
#define fs first
#define sc second
using namespace std;
typedef pair<int, int> pii;
typedef vector<int> vi;
typedef vector<pii> state;

const int dy[] = {0, -1, 0, 1, 0}, dx[] = {0, 0, 1, 0, -1};

inline int encode(const state &x, const int &w) {
  int res = 0, k = 1;
  for (pii p : x) {
    res += k * (p.fs * w + p.sc);
    k <<= 8;
  }
  return res;
}

inline state decode(int x, const int &n, const int &w) {
  int k = 1 << 8;
  state res;
  rep(i, n) {
    int t = x % k;
    res.push_back(pii(t / w, t % w));
    x >>= 8;
  }
  return res;
}

short memo[1 << 24];

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

  int h, w, n;
  string g[16];
  while (cin >> w >> h >> n, w) {
    cin.ignore();

    state start(n), end(n);
    rep(i, h) {
      getline(cin, g[i]);
      rep(j, w) {
        if (islower(g[i][j]))
          start[g[i][j] - 'a'] = pii(i, j);
        if (isupper(g[i][j]))
          end[g[i][j] - 'A'] = pii(i, j);
      }
    }
    int start_id = encode(start, w);
    int end_id = encode(end, w);

    memset(memo, -1, sizeof(memo));
    memo[start_id] = 0;
    queue<int> q;
    q.push(start_id);

    while (q.size()) {
      int cur_id = q.front();
      q.pop();
      state cur = decode(cur_id, n, w);
      if (cur_id == end_id)
        break;

      vi dir(n, 0);
      dir[0] = 1;
      while (dir[n - 1] < 5) {
        state nxt = cur;
        bool f = true;
        for (int i = 0; f && i < n; i++) {
          nxt[i].fs += dy[dir[i]], nxt[i].sc += dx[dir[i]];
          if (g[nxt[i].fs][nxt[i].sc] == '#')
            f = false;

          for (int j = 0; f && j < i; j++) {
            if (nxt[i] == nxt[j])
              f = false;
            if (nxt[i] == cur[j] && nxt[j] == cur[i])
              f = false;
          }
        }

        if (f) {
          int nxt_id = encode(nxt, w);
          if (memo[nxt_id] < 0) {
            memo[nxt_id] = memo[cur_id] + 1;
            q.push(nxt_id);
          }
        }

        dir[0]++;
        for (int i = 0; i < n - 1; i++) {
          if (dir[i] == 5)
            dir[i] = 0, dir[i + 1]++;
        }
      }
    }
    cout << memo[end_id] << endl;
  }
}