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

#include <bits/stdc++.h>
using namespace std;

// 型定義
typedef long long ll;
typedef pair<ll, ll> P;

// forループ
#define REP(i, n) for (ll i = 0; i < (ll)(n); ++i)

// 定数宣言
const int INF = 1e9;
const int MOD = 1e9 + 7;
const ll LINF = 1e18;

// グラフ表現
using Graph = vector<vector<int>>;

// グラフの辺表現
using Edge = map<pair<int, int>, int>;

// n次元配列の初期化。第２引数の型のサイズごとに初期化していく。
template <typename A, size_t N, typename T>
void Fill(A (&array)[N], const T &val) {
  std::fill((T *)array, (T *)(array + N), val);
}

// 最大公約数
ll gcd(ll a, ll b) {
  if (a % b == 0)
    return (b);
  else
    return (gcd(b, a % b));
}

// 最小公倍数
ll lcm(ll a, ll b) { return a / gcd(a, b) * b; }

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

int main() {
  cout << fixed << setprecision(15);

  ll H, W, sx, sy, gx, gy;
  cin >> H >> W;
  cin >> sx >> sy;
  cin >> gx >> gy;

  // indexが0からなので1減らす
  sx--;
  sy--;
  gy--;
  gx--;

  vector<string> S(H);
  REP(i, H) { cin >> S[i]; }
  vector<vector<ll>> v(H, vector<ll>(W, LINF));

  // キューを準備
  deque<P> que;

  // 探索の初期値を入れる
  que.emplace_back(sx, sy);
  v[sx][sy] = 0;

  while (true) {
    // 　もしも探索地点がゴールならば現在の歩数を探索終了
    if (que.empty()) {
      break;
    }
    // キューの中身を取り出す
    P p = que.front();
    que.pop_front();
    int x = p.first;
    int y = p.second;
    int s = v[x][y];

    // if(v[x][y] != s) continue;

    // 4方向へ繰り返す
    REP(i, 4) {
      int nx = x + dx[i];
      int ny = y + dy[i];
      // 移動すると範囲外になったり、#だったり、探索済みだったら終了する
      if (nx < 0 || nx >= H || ny < 0 || ny >= W || v[nx][ny] <= s ||
          S[nx][ny] == '#')
        continue;
      // 未探索だったら、キューに入れて現在の距離を記録
      que.emplace_front(nx, ny);
      v[nx][ny] = s;
    }

    // ワープを使う場合
    for (ll ei = -2; ei <= 2; ei++) {
      for (ll ej = -2; ej <= 2; ej++) {
        int nx = x + ei;
        int ny = y + ej;
        // 移動すると範囲外になったり、#だったり、探索済みだったら終了する
        if (nx < 0 || nx >= H || ny < 0 || ny >= W || v[nx][ny] <= s + 1 ||
            S[nx][ny] == '#')
          continue;
        // 未探索だったら、キューに入れて現在の距離を記録
        que.emplace_back(nx, ny);
        v[nx][ny] = s + 1;
      }
    }
  }

  // REP(i, H){
  //     REP(j, W){
  //         cout << i << ":" << j << ":" << v[i][j] << endl;
  //     }
  // }
  ll ans = v[gx][gy];
  if (ans == LINF)
    ans = -1;
  cout << ans << endl;

  return 0;
}

Error: TLE

Fixed submission:

#include <bits/stdc++.h>
using namespace std;

// 型定義
typedef long long ll;
typedef pair<ll, ll> P;

// forループ
#define REP(i, n) for (ll i = 0; i < (ll)(n); ++i)

// 定数宣言
const int INF = 1e9;
const int MOD = 1e9 + 7;
const ll LINF = 1e18;

// グラフ表現
using Graph = vector<vector<int>>;

// グラフの辺表現
using Edge = map<pair<int, int>, int>;

// n次元配列の初期化。第２引数の型のサイズごとに初期化していく。
template <typename A, size_t N, typename T>
void Fill(A (&array)[N], const T &val) {
  std::fill((T *)array, (T *)(array + N), val);
}

// 最大公約数
ll gcd(ll a, ll b) {
  if (a % b == 0)
    return (b);
  else
    return (gcd(b, a % b));
}

// 最小公倍数
ll lcm(ll a, ll b) { return a / gcd(a, b) * b; }

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

int main() {
  cout << fixed << setprecision(15);

  ll H, W, sx, sy, gx, gy;
  cin >> H >> W;
  cin >> sx >> sy;
  cin >> gx >> gy;

  // indexが0からなので1減らす
  sx--;
  sy--;
  gy--;
  gx--;

  vector<string> S(H);
  REP(i, H) { cin >> S[i]; }
  vector<vector<ll>> v(H, vector<ll>(W, LINF));

  // キューを準備
  deque<P> que;

  // 探索の初期値を入れる
  que.emplace_back(sx, sy);
  v[sx][sy] = 0;

  while (true) {
    // 　もしも探索地点がゴールならば現在の歩数を探索終了
    if (que.empty()) {
      break;
    }
    // キューの中身を取り出す
    P p = que.front();
    que.pop_front();
    int x = p.first;
    int y = p.second;
    int s = v[x][y];

    if (v[x][y] != s)
      continue;

    // 4方向へ繰り返す
    REP(i, 4) {
      int nx = x + dx[i];
      int ny = y + dy[i];
      // 移動すると範囲外になったり、#だったり、探索済みだったら終了する
      if (nx < 0 || nx >= H || ny < 0 || ny >= W || v[nx][ny] <= s ||
          S[nx][ny] == '#')
        continue;
      // 未探索だったら、キューに入れて現在の距離を記録
      que.emplace_front(nx, ny);
      v[nx][ny] = s;
    }

    // ワープを使う場合
    for (ll ei = -2; ei <= 2; ei++) {
      for (ll ej = -2; ej <= 2; ej++) {
        int nx = x + ei;
        int ny = y + ej;
        // 移動すると範囲外になったり、#だったり、探索済みだったら終了する
        if (nx < 0 || nx >= H || ny < 0 || ny >= W || v[nx][ny] <= s + 1 ||
            S[nx][ny] == '#')
          continue;
        // 未探索だったら、キューに入れて現在の距離を記録
        que.emplace_front(nx, ny);
        v[nx][ny] = s + 1;
      }
    }
  }

  // REP(i, H){
  //     REP(j, W){
  //         cout << i << ":" << j << ":" << v[i][j] << endl;
  //     }
  // }
  ll ans = v[gx][gy];
  if (ans == LINF)
    ans = -1;
  cout << ans << endl;

  return 0;
}