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

#include <cstdlib>
#include <iostream>
#include <queue>
#include <tuple>
#include <vector>

using namespace std;

struct S {
  int t, y, x, s;
  bool operator<(S s) const { return t > s.t; }
};

int H, W;
char g[52][52];
int INF = 1e9;

vector<int> to_pos(int py1, int px1, int ky, int kx) {
  vector<int> ps(8, INF);
  queue<tuple<int, int, int>> que1;
  que1.push(make_tuple(0, py1, px1));
  bool u1[50][50] = {};
  while (!que1.empty()) {
    int t1, y1, x1;
    tie(t1, y1, x1) = que1.front();
    que1.pop();
    if (u1[y1][x1]++)
      continue;
    for (int i = 0; i < 8; i++) {
      static int dy[] = {-1, -1, 0, 1, 2, 2, 1, 0};
      static int dx[] = {0, 1, 2, 2, 1, 0, -1, -1};
      if (y1 == ky + dy[i] && x1 == kx + dx[i]) {
        ps[i] = t1;
      }
    }
    for (int i = 0; i < 4; i++) {
      const static int d[] = {0, 1, 0, -1, 0};
      int ny = y1 + d[i];
      int nx = x1 + d[i + 1];
      if (0 <= ny && ny < H && 0 <= nx && nx < W && g[ny][nx] != '*' &&
          !(ky <= ny && ny < ky + 2 && kx <= nx && nx < kx + 2)) {
        que1.push(make_tuple(t1 + 1, ny, nx));
      }
    }
  }
  return ps;
}

vector<int> move_pawns(int py1, int px1, int py2, int px2, int ky, int kx) {
  auto p1 = to_pos(py1, px1, ky, kx);
  auto p2 = to_pos(py2, px2, ky, kx);
  vector<int> r(4);
  for (int i = 0; i < 4; i++) {
    r[i] = min(p1[i * 2] + p2[i * 2 + 1], p1[i * 2 + 1] + p2[i * 2]);
  }
  return r;
}

int main() {
  for (; cin >> H >> W, H | W;) {
    int ky, kx = -1;
    int sy1, sx1 = -1, sy2, sx2;
    for (int i = 0; i < H; i++) {
      cin >> g[i];
      for (int j = 0; j < W; j++) {
        if (g[i][j] == 'X') {
          if (kx < 0) {
            ky = i;
            kx = j;
          }
        } else if (g[i][j] == '.') {
          if (sx1 < 0) {
            sy1 = i;
            sx1 = j;
          } else {
            sy2 = i;
            sx2 = j;
          }
        }
      }
    }
    if (g[0][0] == 'X') {
      cout << 0 << endl;
    } else {
      auto r = move_pawns(sy1, sx1, sy2, sx2, ky, kx);
      priority_queue<S> que;
      for (int i = 0; i < 4; i++) {
        if (r[i] < INF) {
          que.push({r[i], ky, kx, i});
        }
      }
      bool u[50][50][4] = {};
      while (!que.empty()) {
        auto c = que.top();
        if (c.y == 0 && c.x == 0)
          break;
        que.pop();
        if (u[c.y][c.x][c.s]++)
          continue;
        const static int dy[] = {-1, 0, 1, 0};
        const static int dx[] = {0, 1, 0, -1};
        que.push({c.t + 1, c.y + dy[c.s], c.x + dx[c.s], c.s ^ 2});
        const static int py[][2] = {{-1, -1}, {0, 1}, {2, 2}, {1, 0}};
        const static int px[][2] = {{0, 1}, {2, 2}, {1, 0}, {-1, -1}};
        auto r = move_pawns(c.y + py[c.s][0], c.x + px[c.s][0],
                            c.y + py[c.s][1], c.x + px[c.s][1], c.y, c.x);
        for (int i = 0; i < 4; i++) {
          if (r[i] < INF) {
            que.push({c.t + r[i], c.y, c.x, i});
          }
        }
      }
      cout << (que.empty() ? -1 : que.top().t) << endl;
    }
  }
}

Error: TLE

Fixed submission:

#include <algorithm>
#include <functional>
#include <iostream>
#include <queue>
#include <set>
#include <vector>

using namespace std;

bool u[52][52][52][52];
bool u2[50][50][2][50][50];

int main() {
  for (int H, W; cin >> H >> W, H | W;) {
    auto inside = [H, W](int y, int x) {
      return 0 <= y && y < H && 0 <= x && x < W;
    };
    char g[52][52];
    int sy[2], sx[2], sn = 0;
    int sky = -1, skx;
    for (int i = 0; i < H; i++) {
      cin >> g[i];
      for (int j = 0; j < W; j++) {
        if (g[i][j] == '.') {
          sy[sn] = i;
          sx[sn] = j;
          sn++;
        }
        if (sky < 0 && g[i][j] == 'X') {
          sky = i;
          skx = j;
        }
      }
    }
    if (g[0][0] == 'X') {
      cout << 0 << endl;
      continue;
    }
    fill(***begin(u), ***end(u), false);
    set<tuple<int, int, int, int, int>> que;
    que.insert(make_tuple(0, sy[0], sx[0], sy[1], sx[1]));
    //    priority_queue<tuple<int,int,int,int,int,int>,vector<tuple<int,int,int,int,int,int>
    //    >,greater<tuple<int,int,int,int,int,int> > > que2;
    set<tuple<int, int, int, int, int, int>> que2;
    while (!que.empty()) {
      static int dy[] = {-1, 0, 1, 0};
      static int dx[] = {0, 1, 0, -1};
      auto c = *que.begin();
      que.erase(que.begin());
      int t, y1, x1, y2, x2;
      tie(t, y1, x1, y2, x2) = c;
      if (u[y1][x1][y2][x2]++)
        continue;
      for (int i = 0; i < 4; i++) {
        int ny1 = y1 + dy[i];
        int nx1 = x1 + dx[i];
        int ny2 = y2 + dy[i];
        int nx2 = x2 + dx[i];
        if (inside(ny1, nx1) && inside(ny2, nx2) && g[ny1][nx1] == 'X' &&
            g[ny2][nx2] == 'X') {
          que2.insert(
              make_tuple(t, min(y1, y2), min(x1, x2), x1 != x2, sky, skx));
        }
      }
      for (int i = 0; i < 2; i++) {
        for (int j = 0; j < 4; j++) {
          int ny1 = i ? y1 + dy[j] : y1;
          int nx1 = i ? x1 + dx[j] : x1;
          int ny2 = i ? y2 : y2 + dy[j];
          int nx2 = i ? x2 : x2 + dx[j];
          if (!inside(ny1, nx1) || !inside(ny2, nx2) ||
              ny1 == ny2 && nx1 == nx2 || g[ny1][nx1] == 'X' ||
              g[ny1][nx1] == '*' || g[ny2][nx2] == 'X' || g[ny2][nx2] == '*')
            continue;
          que.insert(make_tuple(t + 1, ny1, nx1, ny2, nx2));
        }
      }
    }
    fill(****begin(u2), ****end(u2), false);
    while (!que2.empty()) {
      auto c = *que2.begin();
      int t, y, x, d, ky, kx;
      tie(t, y, x, d, ky, kx) = c;
      if (ky == 0 && kx == 0)
        break;
      que2.erase(que2.begin());
      if (u2[y][x][d][ky][kx]++)
        continue;
      //      cout<<ky<<' '<<kx<<endl;
      for (int i = 0; i < 6; i++) {
        static int ndy[2][6] = {{-1, 2, 0, 1, 0, 1}, {0, 0, 1, 1, -1, -1}};
        static int ndx[2][6] = {{0, 0, -1, -1, 1, 1}, {-1, 2, 0, 1, 0, 1}};
        int cy = y + ndy[d][i];
        int cx = x + ndx[d][i];
        if (inside(cy, cx) && g[cy][cx] != '*' &&
            (cy < ky || ky + 2 <= cy || cx < kx || kx + 2 <= cx)) {
          static int hdy[2][6] = {{-1, 1, 0, 1, 0, 1}, {0, 0, 0, 0, -1, -1}};
          static int hdx[2][6] = {{0, 0, -1, -1, 0, 0}, {-1, 1, 0, 1, 0, 1}};
          que2.insert(make_tuple(t + 2, y + hdy[d][i], x + hdx[d][i],
                                 d ^ (i >= 2), ky, kx));
        }
      }
      if (y == ky && d == 0) {
        if (kx - 1 == x) {
          que2.insert(make_tuple(t + 1, y, x + 2, d, ky, kx - 1));
        } else if (kx + 2 == x) {
          que2.insert(make_tuple(t + 1, y, x - 2, d, ky, kx + 1));
        }
      } else if (x == kx && d == 1) {
        if (ky - 1 == y) {
          que2.insert(make_tuple(t + 1, y + 2, x, d, ky - 1, kx));
        } else if (ky + 2 == y) {
          que2.insert(make_tuple(t + 1, y - 2, x, d, ky + 1, kx));
        }
      }
    }
    cout << (que2.empty() ? -1 : get<0>(*que2.begin())) << endl;
  }
}