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

#include <bitset>
#include <queue>
#include <stdio.h>
#include <string.h>
char m[32][32];
const int dx[] = {0, 1, 0, -1, 0}, dy[] = {1, 0, -1, 0, 0};
std::bitset<1 << 24> f;
template <int N> struct S {
  void I2P(int a, int *x, int *y) {
    for (int i = 0; i < N; ++i) {
      y[N - i - 1] = a & 15;
      x[N - i - 1] = (a >> 4) & 15;
      a >>= 8;
    }
  }
  int P2I(int *x, int *y) {
    int res = 0, i;
    for (i = 0; i < N; ++i)
      res = (res << 8) | (x[i] << 4) + y[i];
    return res;
  }
  int EQ(int *x, int *y, int *gx, int *gy) {
    for (int i = 0; i < N; ++i)
      if (x[i] != gx[i] || y[i] != gy[i])
        return 0;
    return 1;
  }
  void G(std::queue<int> &q, int *x, int *y, int *nx, int *ny, int /* i*/) {
    int i, j, k, a;
    for (i = 0; i < 5; ++i) {
      nx[0] = x[0] + dx[i];
      ny[0] = y[0] + dy[i];
      if (m[ny[0]][nx[0]] == '#')
        continue;
      if (N == 1) {
        a = P2I(nx, ny);
        if (!f[a])
          q.push(a);
        continue;
      }
      for (j = 0; j < 5; ++j) {
        nx[1] = x[1] + dx[j];
        ny[1] = y[1] + dy[j];
        if (m[ny[1]][nx[1]] == '#' || nx[0] == nx[1] && ny[0] == ny[1])
          continue;
        if (x[0] == nx[1] && y[0] == ny[1] && x[1] == nx[0] && y[1] == ny[0])
          continue;
        if (N == 2) {
          a = P2I(nx, ny);
          if (!f[a])
            q.push(a);
          continue;
        }
        for (k = 0; k < 5; ++k) {
          nx[2] = x[2] + dx[k];
          ny[2] = y[2] + dy[k];
          if (m[ny[2]][nx[2]] == '#' || nx[0] == nx[2] && ny[0] == ny[2] ||
              nx[1] == nx[2] && ny[1] == ny[2])
            continue;
          if (x[0] == nx[2] && y[0] == ny[2] && x[2] == nx[0] &&
                  y[2] == ny[0] ||
              x[1] == nx[2] && y[1] == ny[2] && x[2] == nx[1] && y[2] == ny[1])
            continue;
          a = P2I(nx, ny);
          if (!f[a])
            q.push(a);
        }
      }
    }
  }
  int F(int (&x)[3], int (&y)[3], int (&gx)[3], int (&gy)[3]) {
    f.reset();
    std::queue<int> q;
    q.push(P2I(x, y));
    q.push(-1);
    int a, res = 0;
    int nx[3], ny[3];
    for (;;) {
      a = q.front();
      q.pop();
      if (a < 0) {
        ++res;
        q.push(a);
        continue;
      }
      if (f[a])
        continue;
      f[a] = true;
      I2P(a, x, y);
      if (EQ(x, y, gx, gy))
        return res;
      G(q, x, y, nx, ny, 0);
    }
  }
};
int main() {
  int h, w, n, i, x[3], y[3], gx[3], gy[3];
  char *p;
  while (scanf("%d%d%d", &w, &h, &n), n) {
    fgets(m[0], 32, stdin);
    for (i = 0; i < h; ++i) {
      fgets(m[i], 32, stdin);
      for (p = m[i]; p = strpbrk(p, "abc"); ++p) {
        y[*p - 'a'] = i;
        x[*p - 'a'] = p - m[i];
      }
      for (p = m[i]; p = strpbrk(p, "ABC"); ++p) {
        gy[*p - 'A'] = i;
        gx[*p - 'A'] = p - m[i];
      }
    }
    int r = (n == 3   ? S<3>().F(x, y, gx, gy)
             : n == 2 ? S<2>().F(x, y, gx, gy)
                      : S<1>().F(x, y, gx, gy));
    printf("%d\\n", r);
  }
  return 0;
}

Error: TLE

Fixed submission:

#include <bitset>
#include <queue>
#include <stdio.h>
#include <string.h>
char m[32][32];
int dx[] = {0, 1, 0, -1, 0}, dy[] = {1, 0, -1, 0, 0};
std::bitset<1 << 24> f;
template <int N> struct S {
  void I2P(int a, int *x, int *y) {
    for (int i = 0; i < N; ++i) {
      y[N - i - 1] = a & 15;
      x[N - i - 1] = (a >> 4) & 15;
      a >>= 8;
    }
  }
  int P2I(int *x, int *y) {
    int res = 0, i;
    for (i = 0; i < N; ++i)
      res = (res << 8) | (x[i] << 4) + y[i];
    return res;
  }
  int EQ(int *x, int *y, int *gx, int *gy) {
    for (int i = 0; i < N; ++i)
      if (x[i] - gx[i] || y[i] - gy[i])
        return 0;
    return 1;
  }
  void G(std::queue<int> &q, int *x, int *y, int *nx, int *ny, int i) {
    int j, k;
    if (i == N) {
      int a = P2I(nx, ny);
      if (f[a])
        return;
      for (j = 0; j < N; ++j)
        for (k = j + 1; k < N; ++k)
          if (x[j] == nx[k] && y[j] == ny[k] && x[k] == nx[j] && y[k] == ny[j])
            return;
      q.push(a);
    } else
      for (k = 0; k < 5; ++k) {
        nx[i] = x[i] + dx[k];
        ny[i] = y[i] + dy[k];
        if (m[ny[i]][nx[i]] == '#')
          continue;
        for (j = 0; j < i; ++j)
          if (nx[i] == nx[j] && ny[i] == ny[j])
            goto END;
        G(q, x, y, nx, ny, i + 1);
      END:;
      }
  }
  int F(int (&x)[3], int (&y)[3], int (&gx)[3], int (&gy)[3]) {
    f.reset();
    std::queue<int> q;
    q.push(P2I(x, y));
    q.push(-1);
    int a, res = 0;
    int nx[3], ny[3];
    for (;;) {
      a = q.front();
      q.pop();
      if (a < 0) {
        ++res;
        q.push(a);
        continue;
      }
      if (f[a])
        continue;
      f[a] = true;
      I2P(a, x, y);
      if (EQ(x, y, gx, gy))
        return res;
      G(q, x, y, nx, ny, 0);
    }
  }
};
int main() {
  int h, w, n, i, x[3], y[3], gx[3], gy[3];
  char *p;
  while (scanf("%d%d%d", &w, &h, &n), n) {
    fgets(m[0], 32, stdin);
    for (i = 0; i < h; ++i) {
      fgets(m[i], 32, stdin);
      for (p = m[i]; p = strpbrk(p, "abc"); ++p) {
        y[*p - 'a'] = i;
        x[*p - 'a'] = p - m[i];
      }
      for (p = m[i]; p = strpbrk(p, "ABC"); ++p) {
        gy[*p - 'A'] = i;
        gx[*p - 'A'] = p - m[i];
      }
    }
    int r = (n == 3   ? S<3>().F(x, y, gx, gy)
             : n == 2 ? S<2>().F(x, y, gx, gy)
                      : S<1>().F(x, y, gx, gy));
    printf("%d\\n", r);
  }
  return 0;
}