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

#include <algorithm>
#include <bitset>
#include <cassert>
#include <climits>
#include <cstdio>
#include <cstring>
#include <deque>
#include <iostream>
#include <map>
#include <set>
#include <sstream>
#include <vector>
#define F first
#define S second
#define rep(i, n) for (int i = 0; i < n; i++)
#define T 0
#define R 1
#define B 2
#define L 3
#define PesIns(a, b, c, d) Pes(PP(P(a.x, a.y), P(b.x, b.y)), P(c, d))
using namespace std;
typedef vector<int> VI;
typedef vector<char> VC;
typedef vector<bool> VB;
typedef vector<VB> VVB;
typedef vector<VVB> VVVB;
typedef vector<VC> VVC;
typedef pair<int, int> P;
typedef pair<P, P> PP;
typedef pair<PP, P> Pes;

struct Point {
  int x, y;
  Point(int x = -1, int y = -1) : x(x), y(y) {}
  bool operator==(const Point &p) const { return (x == p.x && y == p.y); }
  friend ostream &operator<<(ostream &os, const Point &p);
};

ostream &operator<<(ostream &os, const Point &p) {
  os << "(" << p.x << "," << p.y << ")";
}

int H, W;
char G[17][65];
Point K, M;
VVVB visited;
map<Pes, bool> exist;
int dx[] = {0, 1, 0, -1};
int dy[] = {-1, 0, 1, 0};
int add[] = {1, 3};
bool M_ok, K_ok;
int est;

string debug(int d) {
  if (d == 0)
    return "T";

  if (d == 1)
    return "R";

  if (d == 2)
    return "B";

  if (d == 3)
    return "L";

  return "X";
}

void dfs(Point p1, Point p2, int dir1, int dir2, bool f) {

  if (K_ok)
    return;

  if (!f && M_ok)
    return;

  Pes pes = PesIns(p1, p2, dir1, dir2);
  if (exist[pes])
    return;
  exist[pes] = true;

  if (f && G[p2.y + dy[dir2]][p2.x + dx[dir2]] !=
               '#') // ループ内ではなくここでカットする
    return;

  // cout << "----" << endl;
  // cout << p1 << " " << p2 << " " << debug(dir1) << " " << debug(dir2)  << " M
  // = " << M<< endl;

  while (G[p1.y + dy[dir1]][p1.x + dx[dir1]] != '#')
    p1.x += dx[dir1], p1.y += dy[dir1];

  if (f && p1 == M && p1 == p2 && G[M.y + dy[dir2]][M.x + dx[dir2]] == '.') {
    K_ok = true;
    return;
  } else if (!f && p1 == M) {
    M_ok = true;
    return;
  }

  if (f) {
    while (G[p2.y][p2.x] != '#') // 一つ一つ戻りながら全探索
    {
      rep(i, 2) {
        dfs(p1, p2, (dir1 + add[i]) % 4, (dir2 + add[i]) % 4, f);

        if (K_ok)
          return;
      }

      p2.x += dx[(dir2 + 2) % 4],
          p2.y += dy[(dir2 + 2) % 4]; // ここでやらないと最初の状態がとばされる
    }
    p2.x += dx[dir2], p2.y += dy[dir2];
  } else {
    rep(i, 2) {
      dfs(p1, p2, (dir1 + add[i]) % 4, dir2, f);
      if (M_ok)
        return;
    }
  }
  if (p1 == M && p1 == p2 && G[M.y + dy[dir2]][M.x + dx[dir2]] == '.') {

    K_ok = true;
    return;
  } else if (!f && p1 == M) {
    M_ok = true;
    return;
  }
}

int main() {

  while (cin >> W >> H, H | W) {

    M_ok = K_ok = false;
    exist.clear();
    visited.clear();
    visited.resize(4);
    rep(i, 4) visited[i].resize(H);

    rep(i, H) {
      rep(j, 4) visited[j][i].resize(W);
      string line;
      cin >> line;
      rep(j, W) {
        rep(k, 4) visited[k][i][j] = false;
        G[i][j] = line[j];

        if (G[i][j] == 'K')
          K = Point(j, i);
        else if (G[i][j] == 'M')
          M = Point(j, i);
      }
    }

    int inidir = -1;
    rep(i, 4) if (G[K.y + dy[i]][K.x + dx[i]] == '.') inidir = i;
    dfs(K, Point(-1, -1), inidir, -1, false);
    rep(i, 4) {
      dfs(K, K, inidir, i, true);

      if (K_ok)
        break;
    }
    if (K_ok)
      cout << "He can accomplish his mission." << endl;
    else if (M_ok)
      cout << "He cannot return to the kitchen." << endl;
    else
      cout << "He cannot bring tea to his master." << endl;
  }
  return 0;
}

Error: TLE

Fixed submission:

#include <algorithm>
#include <cassert>
#include <climits>
#include <cstdio>
#include <deque>
#include <iostream>
#include <map>
#include <vector>
#define F first
#define S second
#define T 0
#define R 1
#define B 2
#define L 3
#define all(n) n.begin(), n.end()
#define REP(i, s, n) for (int i = s; i < n; i++)
#define rep(i, n) REP(i, 0, n)
using namespace std;
typedef vector<int> VI;
typedef deque<int> DI;
typedef vector<char> VC;
typedef vector<VC> VVC;
typedef pair<int, int> P;
typedef vector<P> VP;
typedef vector<bool> VB;
typedef vector<VB> VVB;
typedef vector<VVB> VVVB;
P K, M;
int W, H;
int dx[] = {0, 1, 0, -1}; // T R B L
int dy[] = {-1, 0, 1, 0};
int add[] = {1, 3};
bool M_ok, K_ok;
map<VI, bool> Mcheki;

void Input(VVC &G, VVVB &mincost) {
  G.resize(H);
  mincost.resize(4);
  rep(i, 4) mincost[i].resize(H);
  for (int i = 0; i < H; i++) {
    G[i].resize(W);
    rep(j, 4) mincost[j][i].resize(W);
    string line;
    cin >> line;
    for (int j = 0; j < W; j++) {
      rep(k, 4) mincost[k][i][j] = false;
      G[i][j] = line[j];
      if (line[j] == 'K')
        K = P(j, i);
      else if (line[j] == 'M')
        M = P(j, i);
    }
  }
}

bool check(VVC &G, DI info, int x, int y) {
  int dir = -1;
  rep(i, 4) {
    int nx = x + dx[i];
    int ny = y + dy[i];
    if (G[ny][nx] == '.') {
      dir = i;
      break;
    }
  }

  for (int i = info.size() - 1; i >= 0; i--) {
    while (G[y + dy[dir]][x + dx[dir]] != '#') {
      x += dx[dir];
      y += dy[dir];
    }

    dir = (info[i] == L ? (dir + 1) % 4 : (dir + 3) % 4);
  }

  while (G[y + dy[dir]][x + dx[dir]] != '#') {
    x += dx[dir];
    y += dy[dir];
  }

  return G[y][x] == 'K';
}

void dfs(VVC &G, VVVB mincost, DI info, int x, int y, int dir) {
  if (K_ok)
    return;
  if (mincost[dir][y][x])
    return;

  mincost[dir][y][x] = true;

  while (G[y + dy[dir]][x + dx[dir]] != '#') {
    x += dx[dir];
    y += dy[dir];
  }

  if (G[y][x] == 'M') {

    M_ok = true;
    if (check(G, info, x, y)) {
      K_ok = true;
      return;
    }
  }

  rep(i, 2) {
    if (i == 0)
      info.push_back(R);
    else if (i == 1)
      info.push_back(L);
    dfs(G, mincost, info, x, y, (dir + add[i]) % 4);
    info.pop_back();
  }
}

int main() {

  while (cin >> W >> H, W | H) {
    VVC G;
    VVVB mincost;
    Input(G, mincost);
    M_ok = K_ok = false;
    Mcheki.clear();
    DI info;
    int dir = -1;
    rep(i, 4) {
      if (G[K.S + dy[i]][K.F + dx[i]] == '.')
        dir = i;
    }

    dfs(G, mincost, info, K.F, K.S, dir);

    if (!M_ok)
      cout << "He cannot bring tea to his master." << endl;
    else if (K_ok)
      cout << "He can accomplish his mission." << endl;
    else
      cout << "He cannot return to the kitchen." << endl;

    if (K_ok && !M_ok)
      assert(false);
  }
  return 0;
}