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

#include <cstdlib>
#include <iostream>
#include <vector>
using namespace std;

template <class T> inline void chmin(T &a, const T &b) {
  if (a > b)
    a = b;
}
template <class T> inline void chmax(T &a, const T &b) {
  if (a < b)
    a = b;
}

typedef vector<vector<int>> graph;

constexpr int MAX_N = 900;

enum { ESCAPE, LOOP, CATCH };
enum { Q, A, NUM };

const string message[3] = {
    "Queen can escape.",
    "Queen can not escape and Army can not catch Queen.",
    "Army can catch Queen.",
};

int dp[MAX_N][MAX_N][NUM];

inline int get_index(int x, int y, int w) { return x + y * w; }

inline void add_edge(int a, int b, graph &G) {
  G[a].emplace_back(b);
  G[b].emplace_back(a);
}

inline string solve(int q, int a, const vector<int> &g, const graph &G) {
  const int n = G.size();
  for (int v = 0; v < n; ++v) {
    for (int u = 0; u < n; ++u) {
      dp[v][u][Q] = dp[v][u][A] = LOOP;
    }
  }

  for (int v = 0; v < n; ++v) {
    dp[v][v][Q] = dp[v][v][A] = CATCH;
  }

  for (const auto &e : g) {
    for (int v = 0; v < n; ++v) {
      if (e != v)
        dp[e][v][Q] = ESCAPE;
    }
  }

  while (true) {
    bool update = false;

    for (int v = 0; v < n; ++v) {
      for (int u = 0; u < n; ++u) {
        if (v == u)
          continue;

        // queen turn
        if (dp[v][u][Q] != ESCAPE) {
          const int prev = dp[v][u][Q];
          dp[v][u][Q] = CATCH;
          for (const auto &to : G[v]) {
            chmin(dp[v][u][Q], dp[to][u][A]);
          }
          if (dp[v][u][Q] != prev)
            update = true;
        }

        // army turn
        {
          const int prev = dp[v][u][A];
          dp[v][u][A] = ESCAPE;
          for (const auto &to : G[u]) {
            chmax(dp[v][u][A], dp[v][to][Q]);
          }
          if (dp[v][u][A] != prev)
            update = true;
        }
      }
    }

    if (!update)
      break;
  }

  return message[dp[q][a][Q]];
}

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

  for (int w, h; cin >> w >> h && w;) {
    vector<string> field(h);
    for (auto &e : field)
      cin >> e;

    const int n = w * h;
    int q, a;
    vector<int> g;

    graph G(n);

    for (int i = 0; i < h; ++i) {
      for (int j = 0; j < w; ++j) {
        if (field[i][j] == '#')
          continue;

        const int v = get_index(j, i, w);

        switch (field[i][j]) {
        case 'Q':
          q = v;
          break;
        case 'A':
          a = v;
          break;
        case 'E':
          g.emplace_back(v);
          break;
        }

        add_edge(v, v, G);

        if (i < h - 1) {
          if (field[i + 1][j] != '#') {
            add_edge(v, get_index(j, i + 1, w), G);
          }
        }

        if (j < w - 1) {
          if (field[i][j + 1] != '#') {
            add_edge(v, get_index(j + 1, i, w), G);
          }
        }
      }
    }

    cout << solve(q, a, g, G) << endl;
  }

  return EXIT_SUCCESS;
}

Error: TLE

Fixed submission:

#include <algorithm>
#include <cstdlib>
#include <iostream>
#include <vector>
using namespace std;

template <class T> inline void chmin(T &a, const T &b) {
  if (a > b)
    a = b;
}
template <class T> inline void chmax(T &a, const T &b) {
  if (a < b)
    a = b;
}

typedef vector<vector<int>> graph;

constexpr int INF = (1 << 29);
constexpr int MAX_N = 900;

enum { Q, A, NUM };

int dp[MAX_N][MAX_N][NUM];

inline int get_index(int x, int y, int w) { return x + y * w; }

inline void add_edge(int a, int b, graph &G) {
  G[a].emplace_back(b);
  G[b].emplace_back(a);
}

inline string solve(int q, int a, const vector<int> &g, const graph &G) {
  fill_n((int *)dp, sizeof(dp) / sizeof(int), INF / 2);

  const int n = G.size();
  for (int v = 0; v < n; ++v) {
    dp[v][v][Q] = dp[v][v][A] = INF;
  }

  for (const auto &e : g) {
    for (int v = 0; v < n; ++v) {
      if (e != v)
        dp[e][v][Q] = 0;
    }
  }

  for (int iter = 0; iter < 2 * n; ++iter) {
    for (int v = 0; v < n; ++v) {
      for (int u = 0; u < n; ++u) {
        if (v == u)
          continue;

        // queen turn
        if (dp[v][u][Q] != 0) {
          dp[v][u][Q] = INF;
          for (const auto &to : G[v]) {
            chmin(dp[v][u][Q], dp[to][u][A]);
          }
        }

        // army turn
        dp[v][u][A] = 0;
        for (const auto &to : G[u]) {
          chmax(dp[v][u][A], dp[v][to][Q] + 1);
        }
      }
    }
  }

  if (dp[q][a][Q] >= INF)
    return "Army can catch Queen.";
  if (dp[q][a][Q] >= INF / 2)
    return "Queen can not escape and Army can not catch Queen.";
  return "Queen can escape.";
}

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

  for (int w, h; cin >> w >> h && w;) {
    vector<string> field(h);
    for (auto &e : field)
      cin >> e;

    const int n = w * h;
    int q, a;
    vector<int> g;

    graph G(n);

    for (int i = 0; i < h; ++i) {
      for (int j = 0; j < w; ++j) {
        if (field[i][j] == '#')
          continue;

        const int v = get_index(j, i, w);

        switch (field[i][j]) {
        case 'Q':
          q = v;
          break;
        case 'A':
          a = v;
          break;
        case 'E':
          g.emplace_back(v);
          break;
        }

        add_edge(v, v, G);

        if (i < h - 1) {
          if (field[i + 1][j] != '#') {
            add_edge(v, get_index(j, i + 1, w), G);
          }
        }

        if (j < w - 1) {
          if (field[i][j + 1] != '#') {
            add_edge(v, get_index(j + 1, i, w), G);
          }
        }
      }
    }

    cout << solve(q, a, g, G) << endl;
  }

  return EXIT_SUCCESS;
}