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

// ヘッダー
#include <bits/stdc++.h>
using namespace std;

// 型定義
typedef long long ll;

// 定数
const ll INF = 1e+18;
const int MOD = 1e+9 + 7;

// REPマクロ
#define REP(i, n) for (ll i = 0; i < (ll)(n); i++)
#define REPD(i, n) for (ll i = n - 1; i >= 0; i--)
#define REP2(i, a, b) for (ll i = a; i < (ll)(b); i++)
#define REPD2(i, a, b) for (ll i = a; i > (ll)(b); i--)

// 多次元 vector 生成
template <class T> vector<T> make_vec(size_t a) { return vector<T>(a); }
template <class T, class... Ts> auto make_vec(size_t a, Ts... ts) {
  return vector<decltype(make_vec<T>(ts...))>(a, make_vec<T>(ts...));
}

// vectorの扱い
#define ALL(x) (x).begin(), (x).end() // sortなどの引数省略
#define SIZE(x) ((ll)(x).size())      // size
#define MAX(x) *max_element(ALL(x))   // 最大値
#define MIN(x) *min_element(ALL(x))   // 最小値

// 省略
using vi = vector<int>;
using vii = vector<vector<int>>;
using vl = vector<ll>;
using vll = vector<vector<ll>>;
using pii = pair<int, int>;
using pll = pair<ll, ll>;

const vector<pll> p = {{0, 1}, {0, -1}, {-1, 0}, {1, 0}};

int main() {
  ll H, W, K;
  cin >> H >> W >> K;
  ll x1, y1, x2, y2;
  cin >> x1 >> y1 >> x2 >> y2;
  vector<vector<char>> c(H + 10, vector<char>(W + 10, '@'));
  REP(i, H) REP(j, W) cin >> c[i + 1][j + 1];
  // ダイクストラ
  auto dist = make_vec<ll>(H + 10, W + 10, 5);
  REP(i, H + 10) REP(j, W + 10) REP(k, 5) dist[i][j][k] = INF;

  // dist,x,y,方向(0:上 1:下 2:左 3:右),連続cnt
  priority_queue<tuple<ll, ll, ll, ll, ll>, vector<tuple<ll, ll, ll, ll, ll>>,
                 greater<tuple<ll, ll, ll, ll, ll>>>
      que;

  // 初期条件 (頂点 0 を初期ノードとする)
  dist[x1][y1][4] = 0;
  que.push(make_tuple(0, x1, y1, 4, 0)); // 0 を橙色頂点にする

  // 開始 (キューが空になるまで探索を行う)
  while (!que.empty()) {
    tuple<ll, ll, ll, ll, ll> t =
        que.top(); // 優先度キューから先頭頂点を取り出す
    que.pop();
    ll d = get<0>(t);
    ll x = get<1>(t);
    ll y = get<2>(t);
    ll direct = get<3>(t);
    ll cnt = get<4>(t);

    if (dist[x][y][direct] < d)
      continue;
    // v から辿れる頂点をすべて調べる
    REP(i, p.size()) {
      pll next = p[i];
      ll nx = x + next.first;
      ll ny = y + next.second;

      if (c[nx][ny] == '@')
        continue; // 行けない行き先ならパス

      ll nd = dist[x][y][direct];
      ll ncnt = cnt;

      if (direct != i) { // 方向転換
        ncnt = 1;
        nd++;
      } else { // 方向同じ
        ncnt++;
        if (ncnt >= K + 1) {
          ncnt = 1;
          nd++;
        }
      }

      // 新たな頂点 nv について距離が短いなら更新
      if (nd < dist[nx][ny][i]) {
        dist[nx][ny][i] = nd;
        que.push(make_tuple(nd, nx, ny, i, ncnt));
      }
    }
  }

  ll ans = INF;
  REP(i, 5) ans = min(ans, dist[x2][y2][i]);
  if (ans == INF)
    ans = -1;
  cout << ans << endl;
}

Error: TLE

Fixed submission:

// ヘッダー
#include <bits/stdc++.h>
using namespace std;

// 型定義
typedef long long ll;

// 定数
const ll INF = 1e+18;
const int MOD = 1e+9 + 7;

// REPマクロ
#define REP(i, n) for (ll i = 0; i < (ll)(n); i++)
#define REPD(i, n) for (ll i = n - 1; i >= 0; i--)
#define REP2(i, a, b) for (ll i = a; i < (ll)(b); i++)
#define REPD2(i, a, b) for (ll i = a; i > (ll)(b); i--)

// 多次元 vector 生成
template <class T> vector<T> make_vec(size_t a) { return vector<T>(a); }
template <class T, class... Ts> auto make_vec(size_t a, Ts... ts) {
  return vector<decltype(make_vec<T>(ts...))>(a, make_vec<T>(ts...));
}

// vectorの扱い
#define ALL(x) (x).begin(), (x).end() // sortなどの引数省略
#define SIZE(x) ((ll)(x).size())      // size
#define MAX(x) *max_element(ALL(x))   // 最大値
#define MIN(x) *min_element(ALL(x))   // 最小値

// 省略
using vi = vector<int>;
using vii = vector<vector<int>>;
using vl = vector<ll>;
using vll = vector<vector<ll>>;
using pii = pair<int, int>;
using pll = pair<ll, ll>;

const vector<pll> p = {{0, 1}, {0, -1}, {-1, 0}, {1, 0}};
int main() {
  ll H, W, K;
  cin >> H >> W >> K;
  ll x1, y1, x2, y2;
  cin >> x1 >> y1 >> x2 >> y2;
  vector<vector<char>> c(H + 10, vector<char>(W + 10, '@'));
  REP(i, H) REP(j, W) cin >> c[i + 1][j + 1];
  // ダイクストラ
  vll dist(H + 10, vl(W + 10, INF));

  // dist,x,y,方向(0:上 1:下 2:左 3:右),連続cnt
  priority_queue<tuple<ll, ll, ll, ll, ll>, vector<tuple<ll, ll, ll, ll, ll>>,
                 greater<tuple<ll, ll, ll, ll, ll>>>
      que;

  // 初期条件 (頂点 0 を初期ノードとする)
  dist[x1][y1] = 0;
  que.push(make_tuple(0, x1, y1, -1, 0)); // 0 を橙色頂点にする

  // 開始 (キューが空になるまで探索を行う)
  while (!que.empty()) {
    tuple<ll, ll, ll, ll, ll> t =
        que.top(); // 優先度キューから先頭頂点を取り出す
    que.pop();
    ll d = get<0>(t);
    ll x = get<1>(t);
    ll y = get<2>(t);
    ll direct = get<3>(t);
    ll cnt = get<4>(t);

    if (dist[x][y] < d)
      continue;
    // v から辿れる頂点をすべて調べる
    REP(i, p.size()) {
      pll next = p[i];
      ll nx = x + next.first;
      ll ny = y + next.second;

      if (c[nx][ny] == '@')
        continue; // 行けない行き先ならパス

      ll nd = dist[x][y];
      ll ncnt = cnt;

      if (direct != i) { // 方向転換
        ncnt = 1;
        nd++;
      } else { // 方向同じ
        ncnt++;
        if (ncnt >= K + 1) {
          ncnt = 1;
          nd++;
        }
      }

      // 新たな頂点 nv について距離が短いなら更新
      if (nd <= dist[nx][ny]) {
        dist[nx][ny] = nd;
        que.push(make_tuple(nd, nx, ny, i, ncnt));
      }
    }
  }

  if (dist[x2][y2] == INF)
    dist[x2][y2] = -1;
  cout << dist[x2][y2] << endl;
}