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

#include <bits/stdc++.h>
#define INF (1e9)
using namespace std;
typedef pair<int, int> P;
typedef pair<P, P> P2;
typedef pair<int, P> P3;

string s[55];
int h, w;

int Ady[4] = {-1, 0, 2, 1};
int Adx[4] = {0, 2, 1, -1};
int Bdy[4] = {-1, 1, 2, 0};
int Bdx[4] = {1, 2, 0, -1};

int bfs(P st, P g) {

  int d[55][55];
  queue<P3> q;

  for (int i = 0; i < h; i++)
    for (int j = 0; j < w; j++)
      d[i][j] = INF;

  d[st.first][st.second] = 0;
  q.push(P3(0, st));

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

  while (!q.empty()) {

    P3 t = q.front();
    q.pop();

    int cost = t.first;
    int y = t.second.first;
    int x = t.second.second;

    for (int i = 0; i < 4; i++) {
      int ny = y + dy[i];
      int nx = x + dx[i];
      if (ny < 0 || nx < 0 || h <= ny || w <= nx)
        continue;
      if (s[ny][nx] == '*')
        continue;
      if (d[ny][nx] != INF)
        continue;
      d[ny][nx] = cost + 1;
      q.push(P3(cost + 1, P(ny, nx)));
    }
  }

  return d[g.first][g.second];
}

int min_cost2(P A, P B, P C, P D) {

  int r = bfs(A, B);

  r += bfs(C, D);

  if (r > INF)
    r = INF;

  return r;
}

int min_cost(vector<P> start, P A, P B, P C) {

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

  P g1 = start[0], g2 = start[1];

  for (int i = 0; i < 4; i++)
    s[C.first + dy[i]][C.second + dx[i]] = '*';

  int res = INF;

  res = min(res, min_cost2(A, g1, B, g2));
  res = min(res, min_cost2(A, g2, B, g1));

  for (int i = 0; i < 4; i++)
    s[C.first + dy[i]][C.second + dx[i]] = '.';

  return res;
}

int d[55][55][4];

bool check(P p) {
  if (p.first < 0 || h <= p.first || p.second < 0 || w <= p.second)
    return false;
  if (s[p.first][p.second] == '*')
    return false;
  return true;
}

vector<P> get(P A, int idx) {

  vector<P> res;

  res.push_back(P(A.first + Ady[idx], A.second + Adx[idx]));
  res.push_back(P(A.first + Bdy[idx], A.second + Bdx[idx]));

  return res;
}

priority_queue<P2, vector<P2>, greater<P2>> q;

int dijkstra() {

  int res = INF;

  while (!q.empty()) {

    P2 t = q.top();
    q.pop();

    int cost = t.first.first;
    int y = t.first.second;
    int x = t.second.first;
    int idx = t.second.second;

    if (y == 0 && x == 0)
      res = min(res, cost);

    if (d[y][x][idx] < cost)
      continue;

    for (int i = 0; i < 4; i++) {

      P A = P(y + Ady[i], x + Adx[i]);
      P B = P(y + Bdy[i], x + Bdx[i]);

      if (!check(A) || !check(B))
        continue;

      vector<P> start = get(P(y, x), idx);

      if (!check(start[0]) || !check(start[1]))
        continue;

      int add_cost = min_cost(start, A, B, P(y, x));

      if (add_cost == INF)
        continue;

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

      int ny = y + dy[i], nx = x + dx[i];
      int ncost = cost + add_cost + 1;

      if (d[ny][nx][(i + 2) % 4] > ncost) {
        d[ny][nx][(i + 2) % 4] = ncost;
        q.push(P2(P(ncost, ny), P(nx, (i + 2) % 4)));
      }
    }
  }

  if (res == INF)
    res = -1;

  return res;
}

int main() {

  while (1) {

    cin >> h >> w;
    if (!h && !w)
      break;

    vector<P> start;
    int sy = -1, sx;

    for (int i = 0; i < h; i++) {
      cin >> s[i];
      for (int j = 0; j < w; j++) {
        if (s[i][j] == '.')
          start.push_back(P(i, j));
        if (sy == -1 && s[i][j] == 'X')
          sy = i, sx = j;
      }
    }

    for (int i = 0; i < h; i++)
      for (int j = 0; j < w; j++)
        for (int k = 0; k < 4; k++)
          d[i][j][k] = INF;

    for (int i = 0; i < 4; i++) {

      P A = P(sy + Ady[i], sx + Adx[i]);
      P B = P(sy + Bdy[i], sx + Bdx[i]);

      if (!check(A) || !check(B))
        continue;

      int cost = min_cost(start, A, B, P(sy, sx));

      d[sy][sx][i] = cost;

      q.push(P2(P(cost, sy), P(sx, i)));
    }

    if (sy == 0 && sx == 0)
      cout << 0 << endl;
    else
      cout << dijkstra() << endl;

    while (!q.empty())
      q.pop();
  }

  return 0;
}

Error: TLE

Fixed submission:

#include <bits/stdc++.h>
#define INF (1e9)
using namespace std;
typedef pair<int, int> P;
typedef pair<P, P> P2;
typedef pair<int, P> P3;

string s[55];
int h, w;

int Ady[4] = {-1, 0, 2, 1};
int Adx[4] = {0, 2, 1, -1};
int Bdy[4] = {-1, 1, 2, 0};
int Bdx[4] = {1, 2, 0, -1};

int bfs(P st, P g) {

  int d[55][55];
  queue<P3> q;

  for (int i = 0; i < h; i++)
    for (int j = 0; j < w; j++)
      d[i][j] = INF;

  d[st.first][st.second] = 0;
  q.push(P3(0, st));

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

  while (!q.empty()) {

    P3 t = q.front();
    q.pop();

    int cost = t.first;
    int y = t.second.first;
    int x = t.second.second;

    for (int i = 0; i < 4; i++) {
      int ny = y + dy[i];
      int nx = x + dx[i];
      if (ny < 0 || nx < 0 || h <= ny || w <= nx)
        continue;
      if (s[ny][nx] == '*')
        continue;
      if (d[ny][nx] != INF)
        continue;
      d[ny][nx] = cost + 1;
      q.push(P3(cost + 1, P(ny, nx)));
    }
  }

  return d[g.first][g.second];
}

int min_cost2(P A, P B, P C, P D) {

  int r = bfs(A, B);

  s[B.first][B.second] = '*';

  r += bfs(C, D);

  s[B.first][B.second] = '.';

  if (r > INF)
    r = INF;

  return r;
}

int min_cost(vector<P> start, P A, P B, P C) {

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

  P g1 = start[0], g2 = start[1];

  for (int i = 0; i < 4; i++)
    s[C.first + dy[i]][C.second + dx[i]] = '*';

  int res = INF;

  res = min(res, min_cost2(A, g1, B, g2));
  res = min(res, min_cost2(A, g2, B, g1));
  res = min(res, min_cost2(B, g1, A, g2));
  res = min(res, min_cost2(B, g2, A, g1));

  for (int i = 0; i < 4; i++)
    s[C.first + dy[i]][C.second + dx[i]] = '.';

  return res;
}

int d[55][55][4];

bool check(P p) {
  if (p.first < 0 || h <= p.first || p.second < 0 || w <= p.second)
    return false;
  if (s[p.first][p.second] == '*')
    return false;
  return true;
}

vector<P> get(P A, int idx) {

  vector<P> res;

  res.push_back(P(A.first + Ady[idx], A.second + Adx[idx]));
  res.push_back(P(A.first + Bdy[idx], A.second + Bdx[idx]));

  return res;
}

priority_queue<P2, vector<P2>, greater<P2>> q;

int dijkstra() {

  int res = INF;

  while (!q.empty()) {

    P2 t = q.top();
    q.pop();

    int cost = t.first.first;
    int y = t.first.second;
    int x = t.second.first;
    int idx = t.second.second;

    if (y == 0 && x == 0)
      res = min(res, cost);

    if (d[y][x][idx] < cost)
      continue;

    for (int i = 0; i < 4; i++) {

      P A = P(y + Ady[i], x + Adx[i]);
      P B = P(y + Bdy[i], x + Bdx[i]);

      if (!check(A) || !check(B))
        continue;

      vector<P> start = get(P(y, x), idx);

      if (!check(start[0]) || !check(start[1]))
        continue;

      int add_cost = min_cost(start, A, B, P(y, x));

      if (add_cost == INF)
        continue;

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

      int ny = y + dy[i], nx = x + dx[i];
      int ncost = cost + add_cost + 1;

      if (d[ny][nx][(i + 2) % 4] > ncost) {
        d[ny][nx][(i + 2) % 4] = ncost;
        q.push(P2(P(ncost, ny), P(nx, (i + 2) % 4)));
      }
    }
  }

  if (res == INF)
    res = -1;

  return res;
}

int main() {

  while (1) {

    cin >> h >> w;
    if (!h && !w)
      break;

    vector<P> start;
    int sy = -1, sx;

    for (int i = 0; i < h; i++) {
      cin >> s[i];
      for (int j = 0; j < w; j++) {
        if (s[i][j] == '.')
          start.push_back(P(i, j));
        if (sy == -1 && s[i][j] == 'X')
          sy = i, sx = j;
      }
    }

    for (int i = 0; i < h; i++)
      for (int j = 0; j < w; j++)
        for (int k = 0; k < 4; k++)
          d[i][j][k] = INF;

    for (int i = 0; i < 4; i++) {

      P A = P(sy + Ady[i], sx + Adx[i]);
      P B = P(sy + Bdy[i], sx + Bdx[i]);

      if (!check(A) || !check(B))
        continue;

      int cost = min_cost(start, A, B, P(sy, sx));

      d[sy][sx][i] = cost;

      q.push(P2(P(cost, sy), P(sx, i)));
    }

    if (sy == 0 && sx == 0)
      cout << 0 << endl;
    else
      cout << dijkstra() << endl;

    while (!q.empty())
      q.pop();
  }

  return 0;
}