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

#include <algorithm>
#include <cstring>
#include <iostream>
#include <queue>
using namespace std;

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

bool lp[30][30];
bool ck[30][30][30][30];
int dist[30][30][30][30];
int relt[30][30][30][30];
int memo[30][30][30][30];
int W, H, gx[900], gy[900], gN;
char f[31][31];

class State {
public:
  int x, y, c;
  State(int x, int y, int c) : x(x), y(y), c(c) {}
};

void bfs(int x, int y) {
  bool hs[30][30] = {0};

  queue<State> q;
  q.push(State(x, y, 0));
  hs[x][y] = 1;

  while (!q.empty()) {
    State s = q.front();
    q.pop();
    dist[x][y][s.x][s.y] = s.c;

    for (int i = 0; i < 4; i++) {
      int tx = s.x + dx[i], ty = s.y + dy[i];
      if (tx < 0 || ty < 0 || tx >= W || ty >= H)
        continue;
      if (f[tx][ty] == '#')
        continue;
      if (hs[tx][ty])
        continue;

      hs[tx][ty] = 1;

      q.push(State(tx, ty, s.c + 1));
    }
  }
}

bool loop(int qx, int qy, int d) {
  int sx = qx + dx[d], sy = qy + dy[d];
  if (sx < 0 || sy < 0 || sx >= W || sy >= H)
    return false;
  if (f[sx][sy] == '#')
    return false;

  bool hs[30][30] = {0};

  queue<State> q;
  q.push(State(sx, sy, 0));
  hs[qx][qy] = 1;
  hs[sx][sy] = 1;

  while (!q.empty()) {
    State s = q.front();
    q.pop();

    for (int i = 0; i < 4; i++) {
      int tx = s.x + dx[i], ty = s.y + dy[i];
      if (tx < 0 || ty < 0 || tx >= W || ty >= H)
        continue;
      if (f[tx][ty] == '#')
        continue;
      if (tx == qx && ty == qy) {
        if (s.c == 0)
          continue;
        else
          return true;
      }
      if (hs[tx][ty])
        continue;

      hs[tx][ty] = 1;

      q.push(State(tx, ty, s.c + 1));
    }
  }

  return false;
}

int judge(int qx, int qy, int ax, int ay) {
  if (qx == ax && qy == ay)
    return -1;
  for (int k = 0; k < gN; k++) {
    if (dist[qx][qy][gx[k]][gy[k]] < dist[ax][ay][gx[k]][gy[k]])
      return 1;
  }

  if (lp[qx][qy])
    return 0;
  return -1;
}

void calcD() {
  for (int i = 0; i < H; i++)
    for (int j = 0; j < W; j++) {
      if (f[j][i] == '#')
        continue;
      bfs(j, i);
    }
}

void Search() {
  for (int i = 0; i < H; i++)
    for (int j = 0; j < W; j++) {
      if (f[j][i] == '#')
        continue;

      for (int k = 0; k < 4; k++) {
        if (loop(j, i, k)) {
          lp[j][i] = true;
          break;
        }
      }

      for (int k = 0; k < H; k++)
        for (int l = 0; l < W; l++) {
          if (f[l][k] == '#')
            continue;
          relt[j][i][l][k] = judge(j, i, l, k);
        }
    }
}

int Aphase(int a, int b, int x, int y);
int Qphase(int a, int b, int x, int y);

int Aphase(int a, int b, int x, int y, int d) {
  if (ck[a][b][x][y])
    return memo[a][b][x][y];
  int ret = relt[a][b][x][y];
  for (int i = 0; i < H; i++)
    for (int j = 0; j < W; j++) {
      if (dist[x][y][j][i] == -1)
        continue;

      if (dist[x][y][j][i] <= d) {
        ret = min(ret, relt[a][b][j][i]);
      }
    }

  for (int i = 0; i < H; i++)
    for (int j = 0; j < W; j++) {
      if (dist[x][y][j][i] == -1)
        continue;
      if (ck[a][b][j][i]) {
        ret = min(ret, memo[a][b][j][i]);
        continue;
      }

      if (relt[a][b][j][i] > ret)
        continue;
      if (dist[x][y][j][i] <= d) {
        ret = min(ret, Qphase(a, b, j, i));
      }
    }
  return ret;
}

int Qphase(int a, int b, int x, int y) {
  if (ck[a][b][x][y])
    return memo[a][b][x][y];
  ck[a][b][x][y] = 1;

  memo[a][b][x][y] = relt[a][b][x][y];
  for (int i = 0; i < H; i++)
    for (int j = 0; j < W; j++) {
      if (f[j][i] == '#')
        continue;
      if (dist[a][b][j][i] >= dist[x][y][j][i])
        continue;
      if (dist[a][b][j][i] == -1)
        continue;
      if (relt[a][b][x][y] >= relt[j][i][x][y])
        continue;

      memo[a][b][x][y] =
          max(memo[a][b][x][y], Aphase(j, i, x, y, dist[a][b][j][i]));
    }

  return memo[a][b][x][y];
}

int main() {
  while (cin >> W >> H, (W || H)) {
    gN = 0;
    int ax, ay, qx, qy;
    memset(lp, 0, sizeof(lp));
    memset(ck, 0, sizeof(ck));

    memset(dist, -1, sizeof(dist));
    for (int i = 0; i < H; i++)
      for (int j = 0; j < W; j++) {
        cin >> f[j][i];
        if (f[j][i] == 'A') {
          ax = j;
          ay = i;
        }
        if (f[j][i] == 'Q') {
          qx = j;
          qy = i;
        }
        if (f[j][i] == 'E') {
          gx[gN] = j;
          gy[gN] = i;
          gN++;
        }
      }
    calcD();
    Search();

    int ret = Qphase(qx, qy, ax, ay);
    if (ret == -1)
      cout << "Army can catch Queen." << endl;
    else if (ret == 0)
      cout << "Queen can not escape and Army can not catch Queen." << endl;
    else
      cout << "Queen can escape." << endl;
  }
}

Error: TLE

Fixed submission:

#include <algorithm>
#include <cstring>
#include <iostream>
#include <queue>
using namespace std;

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

bool lp[30][30];
bool ck[30][30][30][30];
int dist[30][30][30][30];
int relt[30][30][30][30];
int memo[30][30][30][30];
int W, H, gx[900], gy[900], gN;
char f[31][31];

class State {
public:
  int x, y, c;
  State(int x, int y, int c) : x(x), y(y), c(c) {}
};

void bfs(int x, int y) {
  bool hs[30][30] = {0};

  queue<State> q;
  q.push(State(x, y, 0));
  hs[x][y] = 1;

  while (!q.empty()) {
    State s = q.front();
    q.pop();
    dist[x][y][s.x][s.y] = s.c;

    for (int i = 0; i < 4; i++) {
      int tx = s.x + dx[i], ty = s.y + dy[i];
      if (tx < 0 || ty < 0 || tx >= W || ty >= H)
        continue;
      if (f[tx][ty] == '#')
        continue;
      if (hs[tx][ty])
        continue;

      hs[tx][ty] = 1;

      q.push(State(tx, ty, s.c + 1));
    }
  }
}

void calcD() {
  for (int i = 0; i < H; i++)
    for (int j = 0; j < W; j++) {
      if (f[j][i] == '#')
        continue;
      bfs(j, i);
    }
}

bool loop(int qx, int qy, int d) {
  int sx = qx + dx[d], sy = qy + dy[d];
  if (sx < 0 || sy < 0 || sx >= W || sy >= H)
    return false;
  if (f[sx][sy] == '#')
    return false;

  bool hs[30][30] = {0};

  queue<State> q;
  q.push(State(sx, sy, 0));
  hs[qx][qy] = 1;
  hs[sx][sy] = 1;

  while (!q.empty()) {
    State s = q.front();
    q.pop();

    for (int i = 0; i < 4; i++) {
      int tx = s.x + dx[i], ty = s.y + dy[i];
      if (tx < 0 || ty < 0 || tx >= W || ty >= H)
        continue;
      if (f[tx][ty] == '#')
        continue;
      if (tx == qx && ty == qy) {
        if (s.c == 0)
          continue;
        else
          return true;
      }
      if (hs[tx][ty])
        continue;

      hs[tx][ty] = 1;

      q.push(State(tx, ty, s.c + 1));
    }
  }

  return false;
}

int judge(int qx, int qy, int ax, int ay) {
  for (int k = 0; k < gN; k++) {
    if (dist[qx][qy][gx[k]][gy[k]] < dist[ax][ay][gx[k]][gy[k]])
      return 1;
  }

  if (lp[qx][qy])
    return 0;
  return -1;
}

void Search() {
  for (int i = 0; i < H; i++)
    for (int j = 0; j < W; j++) {
      if (f[j][i] == '#')
        continue;
      for (int k = 0; k < 4; k++) {
        if (loop(j, i, k)) {
          lp[j][i] = true;
          break;
        }
      }

      for (int k = 0; k < H; k++)
        for (int l = 0; l < W; l++) {
          if (f[l][k] == '#')
            continue;
          relt[j][i][l][k] = judge(j, i, l, k);
        }
    }
}

int Aphase(int a, int b, int x, int y);
int Qphase(int a, int b, int x, int y);

int Aphase(int a, int b, int x, int y, int d) {
  int ret = relt[a][b][x][y];
  for (int i = 0; i < H; i++)
    for (int j = 0; j < W; j++) {
      if (dist[x][y][j][i] == -1)
        continue;

      if (relt[a][b][j][i] > relt[a][b][x][y])
        continue;
      if (dist[x][y][j][i] <= d) {
        ret = min(ret, relt[a][b][j][i]);
      }
    }

  for (int i = 0; i < H; i++)
    for (int j = 0; j < W; j++) {
      if (dist[x][y][j][i] == -1)
        continue;
      if (ck[a][b][j][i]) {
        ret = min(ret, memo[a][b][j][i]);
        continue;
      }

      if (relt[a][b][j][i] > ret)
        continue;
      if (dist[x][y][j][i] <= d) {
        ret = min(ret, Qphase(a, b, j, i));
      }
    }
  return ret;
}

int Qphase(int a, int b, int x, int y) {
  if (ck[a][b][x][y])
    return memo[a][b][x][y];
  ck[a][b][x][y] = 1;

  memo[a][b][x][y] = relt[a][b][x][y];
  for (int i = 0; i < H; i++)
    for (int j = 0; j < W; j++) {
      if (f[j][i] == '#')
        continue;
      if (dist[a][b][j][i] >= dist[x][y][j][i])
        continue;
      if (dist[a][b][j][i] == -1)
        continue;

      memo[a][b][x][y] =
          max(memo[a][b][x][y], Aphase(j, i, x, y, dist[a][b][j][i]));
    }

  return memo[a][b][x][y];
}

int main() {
  while (cin >> W >> H, (W || H)) {
    int ax, ay, qx, qy;
    gN = 0;
    memset(lp, 0, sizeof(lp));
    memset(dist, -1, sizeof(dist));
    memset(ck, 0, sizeof(ck));
    for (int i = 0; i < H; i++)
      for (int j = 0; j < W; j++) {
        cin >> f[j][i];
        if (f[j][i] == 'A') {
          ax = j;
          ay = i;
        }
        if (f[j][i] == 'Q') {
          qx = j;
          qy = i;
        }
        if (f[j][i] == 'E') {
          gx[gN] = j;
          gy[gN] = i;
          gN++;
        }
      }

    calcD();
    Search();

    int ret = Qphase(qx, qy, ax, ay);
    if (ret == -1)
      cout << "Army can catch Queen." << endl;
    else if (ret == 0)
      cout << "Queen can not escape and Army can not catch Queen." << endl;
    else
      cout << "Queen can escape." << endl;
  }
}