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

#include <bits/stdc++.h>
#define WHOLE(v) (v).begin(), (v).end()
#define REV_WHOLE(v) (v).rbegin(), (v).rend()
using i64 = int64_t;
using namespace std;
template <class F> auto recursive(F f) {
  return [f](auto... a) { return f(f, a...); };
}
template <class T>
using rev_priority_queue = priority_queue<T, vector<T>, greater<T>>;
template <class T> using vector2d = vector<vector<T>>;
struct fixprec {
  int p;
  fixprec(int p) : p(p) {}
};
ostream &operator<<(ostream &o, fixprec f) {
  return o << fixed << setprecision(f.p);
}

template <typename T> using vector3d = vector<vector2d<T>>;

using P = pair<int, int>;

int dir[4][2] = {{0, 1}, {-1, 0}, {0, -1}, {1, 0}};

int main() {
  const int INF = 1e9;
  const int INVALID = -1;
  int H, W, K;
  cin >> H >> W >> K;
  int sy, sx, gy, gx;
  cin >> sy >> sx >> gy >> gx;
  sy--, sx--, gx--, gy--;
  vector2d<int> dist(H, vector<int>(W));
  vector2d<bool> visited(H, vector<bool>(W, false));
  for (int i = 0; i < H; i++) {
    string s;
    cin >> s;
    for (int j = 0; j < W; j++) {
      dist[i][j] = s[j] == '@' ? INVALID : INF;
    }
  }
  queue<P> q;
  q.push({sy, sx});
  dist[sy][sx] = 0;
  for (int l = 0; !q.empty(); l++) {
    for (int n = q.size(); n > 0; n--) {
      int y, x;
      tie(y, x) = q.front();
      q.pop();
      if (dist[y][x] < l || visited[y][x])
        continue;
      visited[y][x] = true;
      for (int d = 0; d < 4; d++) {
        for (int k = 1; k <= K; k++) {
          int ny = y + k * dir[d][0], nx = x + k * dir[d][1];
          if (ny < 0 || H <= ny || nx < 0 || W <= nx)
            break;
          if (dist[ny][nx] <= l)
            break;
          dist[ny][nx] = l + 1;
          q.push({ny, nx});
        }
      }
    }
  }
  int ans = dist[gy][gx];
  cout << (ans == INF ? -1 : ans) << endl;
  return 0;
}

Error: TLE

Fixed submission:

#include <bits/stdc++.h>
#define WHOLE(v) (v).begin(), (v).end()
#define REV_WHOLE(v) (v).rbegin(), (v).rend()
using i64 = int64_t;
using namespace std;
template <class F> auto recursive(F f) {
  return [f](auto... a) { return f(f, a...); };
}
template <class T>
using rev_priority_queue = priority_queue<T, vector<T>, greater<T>>;
template <class T> using vector2d = vector<vector<T>>;
struct fixprec {
  int p;
  fixprec(int p) : p(p) {}
};
ostream &operator<<(ostream &o, fixprec f) {
  return o << fixed << setprecision(f.p);
}

template <typename T> using vector3d = vector<vector2d<T>>;
using State = tuple<int, int, int,
                    int>; // (y, x, n, d) -> 座標(x,y)に手数nで向きdから来た

// 四近傍配列
// 並び順は(y,x), y軸は上下逆
// 2とのxorで方向逆転
// mod4上のインクリメントで反時計回り、デクリメントで時計回りに回転
// 論理積の1の位が左右に方向転換したかを表す。
int dir[4][2] = {{0, 1}, {-1, 0}, {0, -1}, {1, 0}};

int main() {
  const int INF = 1e9;
  int H, W, K;
  cin >> H >> W >> K;
  int sy, sx, gy, gx;
  cin >> sy >> sx >> gy >> gx;
  sy--, sx--, gx--, gy--;
  vector3d<int> ans(4, vector2d<int>(H, vector<int>(W, INF)));
  vector2d<int> c(H, vector<int>(W));
  for (int i = 0; i < H; i++) {
    string s;
    cin >> s;
    for (int j = 0; j < W; j++) {
      c[i][j] = s[j] == '@' ? 0 : 1;
    }
  }
  queue<State> q;
  for (int d = 0; d < 4; d++) {
    q.emplace(sy, sx, 0, d);
  }
  auto is_valid = [&](int y, int x) -> bool {
    return 0 <= y && y < H && 0 <= x && x < W && c[y][x];
  };
  while (!q.empty()) {
    int y, x, n, d;
    tie(y, x, n, d) = q.front();
    q.pop();
    if (ans[d][y][x] < INF)
      continue;
    ans[d][y][x] = n;
    if (gy == y && gx == x) {
      cout << n << endl;
      return 0;
    }
    n++;
    for (int k = 1; k <= K; k++) {
      int cy = y + dir[d][0] * k, cx = x + dir[d][1] * k;
      int ny = cy + dir[d][0], nx = cx + dir[d][1];
      if (is_valid(cy, cx)) {
        if (k == K || !is_valid(ny, nx)) {
          q.emplace(cy, cx, n, d);
        }
        for (int nd = 0; nd < 4; nd++) {
          if (nd == d || nd == (d ^ 2))
            continue;
          q.emplace(cy, cx, n, nd);
        }
      } else {
        break;
      }
    }
  }
  cout << -1 << endl;
  return 0;
}