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

#include <bits/stdc++.h>
using namespace std;
#define rep(i, n) for (ll i = 0; i < n; i++)
#define repl(i, l, r) for (ll i = (l); i < (r); i++)
#define per(i, n) for (ll i = n - 1; i >= 0; i--)
#define perl(i, r, l) for (ll i = r - 1; i >= l; i--)
#define fi first
#define se second
#define pb push_back
#define ins insert
#define all(x) (x).begin(), (x).end()
using ll = long long;
using vl = vector<ll>;
using vvl = vector<vector<ll>>;
const ll MOD = 1000000007;
const ll MOD9 = 998244353;
const int inf = 1e9 + 10;
const ll INF = 4e18;
const ll dy[8] = {1, 0, -1, 0, 1, 1, -1, -1};
const ll dx[8] = {0, -1, 0, 1, 1, -1, 1, -1};
using Graph = vector<vector<ll>>;
double nCk(int n, int k) {
  double res = 1.0;
  for (int i = 0; i < n; i++) {
    res *= 0.5;
  }
  for (int i = 0; i < k; i++) {
    res *= (double)(n - i);
    res /= (double)(k - i);
  }
  return res;
}
struct edge {
  ll to, cost;
};
typedef pair<ll, ll> P;
struct graph {
  ll V;
  vector<vector<edge>> G;
  vector<ll> d;

  graph(ll n) { init(n); }

  void init(ll n) {
    V = n;
    G.resize(V);
    d.resize(V);
    rep(i, V) { d[i] = INF; }
  }

  void add_edge(ll s, ll t, ll cost) {
    edge e;
    e.to = t, e.cost = cost;
    G[s].push_back(e);
  }

  void dijkstra(ll s) {
    rep(i, V) { d[i] = INF; }
    d[s] = 0;
    priority_queue<P, vector<P>, greater<P>> que;
    que.push(P(0, s));
    while (!que.empty()) {
      P p = que.top();
      que.pop();
      ll v = p.second;
      if (d[v] < p.first)
        continue;
      for (auto e : G[v]) {
        if (d[e.to] > d[v] + e.cost) {
          d[e.to] = d[v] + e.cost;
          que.push(P(d[e.to], e.to));
        }
      }
    }
  }
};
class UnionFind {
public:
  ll par[100005];
  ll depth[100005];
  ll nGroup[100005];

  UnionFind(ll n) { init(n); }

  void init(ll n) {
    for (ll i = 0; i < n; i++) {
      par[i] = i;
      depth[i] = 0;
      nGroup[i] = 1;
    }
  }

  ll root(ll x) {
    if (par[x] == x) {
      return x;
    } else {
      return par[x] = root(par[x]);
    }
  }

  bool same(ll x, ll y) { return root(x) == root(y); }

  void unite(ll x, ll y) {
    x = root(x);
    y = root(y);
    if (x == y)
      return;

    if (depth[x] < depth[y]) {
      par[x] = y;
      nGroup[y] += nGroup[x];
      nGroup[x] = 0;
    } else {
      par[y] = x;
      nGroup[x] += nGroup[y];
      nGroup[y] = 0;
      if (depth[x] == depth[y])
        depth[x]++;
    }
  }
};
const ll MAX = 510000;
ll fac[MAX], finv[MAX], inv[MAX];

// テーブルを作る前処理
void COMinit() {
  fac[0] = fac[1] = 1;
  finv[0] = finv[1] = 1;
  inv[1] = 1;
  for (int i = 2; i < MAX; i++) {
    fac[i] = fac[i - 1] * i % MOD;
    inv[i] = MOD - inv[MOD % i] * (MOD / i) % MOD;
    finv[i] = finv[i - 1] * inv[i] % MOD;
  }
}

// 二項係数計算
ll COM(ll n, ll k) {
  if (n < k)
    return 0;
  if (n < 0 || k < 0)
    return 0;
  return fac[n] * (finv[k] * finv[n - k] % MOD) % MOD;
}

vector<ll> depth;
vector<ll> subtree_size;
void dfs(const Graph &G, ll v, ll p, ll d) {
  depth[v] = d;
  for (auto nv : G[v]) {
    if (nv == p)
      continue; // nv が親 p だったらダメ
    dfs(G, nv, v, d + 1);
  }

  // 帰りがけ時に、部分木サイズを求める
  subtree_size[v] = INF; // 自分自身
  vl q;
  for (auto c : G[v]) {
    if (c == p)
      continue;
    q.pb(subtree_size[c]); // 子のサイズを加える
  }
  ll qq = q.size();
  // cout << v << " " << qq << endl;
  if (qq == 0)
    subtree_size[v] = 0;
  else {
    sort(all(q));
    // rep(i,qq)cout << q[i];
    // cout << endl;
    ll caa = 0;
    rep(i, qq) { caa = max(qq + q[i] - i, caa); }
    subtree_size[v] = caa;
  }
}
ll dp[100005][2];
int main() {
  ll H, W;
  cin >> H >> W;
  ll sy, sx, gy, gx, d;
  cin >> sx >> sy >> gx >> gy;
  sx--;
  sy--;
  gx--;
  gy--;
  /* 盤面 */
  vector<string> field(H);
  for (ll h = 0; h < H; ++h)
    cin >> field[h];

  vector<vector<ll>> dist(H, vector<ll>(W, INF));
  // vector<vector<ll> > dist1(H, vector<ll>(W, -1));
  dist[sx][sy] = 0; // スタートを 0 に
  // dist1[sx][sy] = 0;
  //  探索中に各マスはどのマスから来たのかを表す配列
  //  (最短経路長を知るだけなら、これは不要)
  // vector<vector<int> > prev_x(H, vector<int>(W, -1));
  // vector<vector<int> > prev_y(H, vector<int>(W, -1));

  // 「一度見た頂点」のうち「まだ訪れていない頂点」を表すキュー
  deque<pair<ll, ll>> que;
  que.push_front(make_pair(sx, sy)); // スタートを push

  ////////////////////////////////////////
  /* 幅優先探索を実施 */
  ////////////////////////////////////////

  /* キューが空になるまで */
  while (!que.empty()) {
    pair<ll, ll> current_pos =
        que.front(); // キューの先頭を見る (C++ ではこれをしても pop しない)
    ll x = current_pos.first;
    ll y = current_pos.second;
    que.pop_front(); // キューから pop を忘れずに

    // 隣接頂点を探索
    for (ll direction = 0; direction < 4; ++direction) {
      ll next_x = x + dx[direction];
      ll next_y = y + dy[direction];
      if (next_x < 0 || next_x >= H || next_y < 0 || next_y >= W)
        continue; // 場外アウトならダメ
      if (field[next_x][next_y] == '#')
        continue; // 壁はダメ
      d = dist[x][y];
      // まだ見ていない頂点なら push
      if (dist[next_x][next_y] > d) {
        dist[next_x][next_y] = d;
        que.push_front(make_pair(next_x, next_y));
      }
      // prev_x[next_x][next_y] = x;  //
      // どの頂点から情報が伝播して来たか、縦方向の座標をメモ
      // prev_y[next_x][next_y] = y;  //
      // どの頂点から情報が伝播して来たか、横方向の座標をメモ
    }
    for (ll direction = 4; direction < 8; ++direction) {
      ll next_x = x + dx[direction];
      ll next_y = y + dy[direction];
      if (next_x < 0 || next_x >= H || next_y < 0 || next_y >= W)
        continue; // 場外アウトならダメ
      if (field[next_x][next_y] == '#')
        continue; // 壁はダメ
      d = dist[x][y] + 1;
      // まだ見ていない頂点なら push
      if (dist[next_x][next_y] > d) {
        que.push_back(make_pair(next_x, next_y));
        dist[next_x][next_y] = dist[x][y] + 1;
      }
    }
    for (ll direction = 0; direction < 4; ++direction) {
      ll next_x = x + 2 * dx[direction];
      ll next_y = y + 2 * dy[direction];
      if (next_x < 0 || next_x >= H || next_y < 0 || next_y >= W)
        continue; // 場外アウトならダメ
      if (field[next_x][next_y] == '#')
        continue; // 壁はダメ

      d = dist[x][y] + 1;
      if (dist[next_x][next_y] > d) {
        que.push_back(make_pair(next_x, next_y));
        dist[next_x][next_y] = dist[x][y] + 1;
      }
    }
    for (ll direction = 4; direction < 8; ++direction) {
      ll next_x = x + 2 * dx[direction];
      ll next_y = y + 2 * dy[direction];
      if (next_x < 0 || next_x >= H || next_y < 0 || next_y >= W)
        continue; // 場外アウトならダメ
      if (field[next_x][next_y] == '#')
        continue; // 壁はダメ

      d = dist[x][y] + 1;
      if (dist[next_x][next_y] > d) {
        que.push_back(make_pair(next_x, next_y));
        dist[next_x][next_y] = dist[x][y] + 1;
      }
    }
    for (ll direction = 4; direction < 8; ++direction) {
      ll next_x = x + 2 * dx[direction];
      ll next_y = y + dy[direction];
      if (next_x < 0 || next_x >= H || next_y < 0 || next_y >= W)
        continue; // 場外アウトならダメ
      if (field[next_x][next_y] == '#')
        continue; // 壁はダメ

      d = dist[x][y] + 1;
      if (dist[next_x][next_y] > d) {
        que.push_back(make_pair(next_x, next_y));
        dist[next_x][next_y] = dist[x][y] + 1;
      }
    }
    for (ll direction = 4; direction < 8; ++direction) {
      ll next_x = x + dx[direction];
      ll next_y = y + 2 * dy[direction];
      if (next_x < 0 || next_x >= H || next_y < 0 || next_y >= W)
        continue; // 場外アウトならダメ
      if (field[next_x][next_y] == '#')
        continue; // 壁はダメ

      d = dist[x][y] + 1;
      if (dist[next_x][next_y] > d) {
        que.push_back(make_pair(next_x, next_y));
        dist[next_x][next_y] = dist[x][y] + 1;
      }
    }
  }
  if (dist[gx][gy] == INF)
    dist[gx][gy] = -1;
  cout << dist[gx][gy] << endl;
}


Error: TLE

Fixed submission:

#include <bits/stdc++.h>
using namespace std;
#define rep(i, n) for (ll i = 0; i < n; i++)
#define repl(i, l, r) for (ll i = (l); i < (r); i++)
#define per(i, n) for (ll i = n - 1; i >= 0; i--)
#define perl(i, r, l) for (ll i = r - 1; i >= l; i--)
#define fi first
#define se second
#define pb push_back
#define ins insert
#define all(x) (x).begin(), (x).end()
using ll = long long;
using vl = vector<ll>;
using vvl = vector<vector<ll>>;
const ll MOD = 1000000007;
const ll MOD9 = 998244353;
const int inf = 1e9 + 10;
const ll INF = 4e18;
const ll dy[8] = {1, 0, -1, 0, 1, 1, -1, -1};
const ll dx[8] = {0, -1, 0, 1, 1, -1, 1, -1};
using Graph = vector<vector<ll>>;
double nCk(int n, int k) {
  double res = 1.0;
  for (int i = 0; i < n; i++) {
    res *= 0.5;
  }
  for (int i = 0; i < k; i++) {
    res *= (double)(n - i);
    res /= (double)(k - i);
  }
  return res;
}
struct edge {
  ll to, cost;
};
typedef pair<ll, ll> P;
struct graph {
  ll V;
  vector<vector<edge>> G;
  vector<ll> d;

  graph(ll n) { init(n); }

  void init(ll n) {
    V = n;
    G.resize(V);
    d.resize(V);
    rep(i, V) { d[i] = INF; }
  }

  void add_edge(ll s, ll t, ll cost) {
    edge e;
    e.to = t, e.cost = cost;
    G[s].push_back(e);
  }

  void dijkstra(ll s) {
    rep(i, V) { d[i] = INF; }
    d[s] = 0;
    priority_queue<P, vector<P>, greater<P>> que;
    que.push(P(0, s));
    while (!que.empty()) {
      P p = que.top();
      que.pop();
      ll v = p.second;
      if (d[v] < p.first)
        continue;
      for (auto e : G[v]) {
        if (d[e.to] > d[v] + e.cost) {
          d[e.to] = d[v] + e.cost;
          que.push(P(d[e.to], e.to));
        }
      }
    }
  }
};
class UnionFind {
public:
  ll par[100005];
  ll depth[100005];
  ll nGroup[100005];

  UnionFind(ll n) { init(n); }

  void init(ll n) {
    for (ll i = 0; i < n; i++) {
      par[i] = i;
      depth[i] = 0;
      nGroup[i] = 1;
    }
  }

  ll root(ll x) {
    if (par[x] == x) {
      return x;
    } else {
      return par[x] = root(par[x]);
    }
  }

  bool same(ll x, ll y) { return root(x) == root(y); }

  void unite(ll x, ll y) {
    x = root(x);
    y = root(y);
    if (x == y)
      return;

    if (depth[x] < depth[y]) {
      par[x] = y;
      nGroup[y] += nGroup[x];
      nGroup[x] = 0;
    } else {
      par[y] = x;
      nGroup[x] += nGroup[y];
      nGroup[y] = 0;
      if (depth[x] == depth[y])
        depth[x]++;
    }
  }
};
const ll MAX = 510000;
ll fac[MAX], finv[MAX], inv[MAX];

// テーブルを作る前処理
void COMinit() {
  fac[0] = fac[1] = 1;
  finv[0] = finv[1] = 1;
  inv[1] = 1;
  for (int i = 2; i < MAX; i++) {
    fac[i] = fac[i - 1] * i % MOD;
    inv[i] = MOD - inv[MOD % i] * (MOD / i) % MOD;
    finv[i] = finv[i - 1] * inv[i] % MOD;
  }
}

// 二項係数計算
ll COM(ll n, ll k) {
  if (n < k)
    return 0;
  if (n < 0 || k < 0)
    return 0;
  return fac[n] * (finv[k] * finv[n - k] % MOD) % MOD;
}

vector<ll> depth;
vector<ll> subtree_size;
void dfs(const Graph &G, ll v, ll p, ll d) {
  depth[v] = d;
  for (auto nv : G[v]) {
    if (nv == p)
      continue; // nv が親 p だったらダメ
    dfs(G, nv, v, d + 1);
  }

  // 帰りがけ時に、部分木サイズを求める
  subtree_size[v] = INF; // 自分自身
  vl q;
  for (auto c : G[v]) {
    if (c == p)
      continue;
    q.pb(subtree_size[c]); // 子のサイズを加える
  }
  ll qq = q.size();
  // cout << v << " " << qq << endl;
  if (qq == 0)
    subtree_size[v] = 0;
  else {
    sort(all(q));
    // rep(i,qq)cout << q[i];
    // cout << endl;
    ll caa = 0;
    rep(i, qq) { caa = max(qq + q[i] - i, caa); }
    subtree_size[v] = caa;
  }
}
ll dp[100005][2];
int main() {
  ll H, W;
  cin >> H >> W;
  ll sy, sx, gy, gx, d;
  cin >> sx >> sy >> gx >> gy;
  sx--;
  sy--;
  gx--;
  gy--;
  /* 盤面 */
  vector<string> field(H);
  for (ll h = 0; h < H; ++h)
    cin >> field[h];

  vector<vector<ll>> dist(H, vector<ll>(W, -1));
  // vector<vector<ll> > dist1(H, vector<ll>(W, -1));
  dist[sx][sy] = 0; // スタートを 0 に
  // dist1[sx][sy] = 0;
  //  探索中に各マスはどのマスから来たのかを表す配列
  //  (最短経路長を知るだけなら、これは不要)
  // vector<vector<int> > prev_x(H, vector<int>(W, -1));
  // vector<vector<int> > prev_y(H, vector<int>(W, -1));

  // 「一度見た頂点」のうち「まだ訪れていない頂点」を表すキュー
  deque<pair<ll, ll>> que;
  que.push_front(make_pair(sx, sy)); // スタートを push

  ////////////////////////////////////////
  /* 幅優先探索を実施 */
  ////////////////////////////////////////

  /* キューが空になるまで */
  while (!que.empty()) {
    pair<ll, ll> current_pos =
        que.front(); // キューの先頭を見る (C++ ではこれをしても pop しない)
    ll x = current_pos.first;
    ll y = current_pos.second;
    que.pop_front(); // キューから pop を忘れずに

    // 隣接頂点を探索
    for (ll direction = 0; direction < 4; ++direction) {
      ll next_x = x + dx[direction];
      ll next_y = y + dy[direction];
      if (next_x < 0 || next_x >= H || next_y < 0 || next_y >= W)
        continue; // 場外アウトならダメ
      if (field[next_x][next_y] == '#')
        continue; // 壁はダメ
      d = dist[x][y];
      // まだ見ていない頂点なら push
      if (dist[next_x][next_y] == -1) {
        que.push_front(make_pair(next_x, next_y));
        dist[next_x][next_y] = dist[x][y];
      } else if (dist[next_x][next_y] > d) {
        dist[next_x][next_y] = d;
        que.push_front(make_pair(next_x, next_y));
      }
      // prev_x[next_x][next_y] = x;  //
      // どの頂点から情報が伝播して来たか、縦方向の座標をメモ
      // prev_y[next_x][next_y] = y;  //
      // どの頂点から情報が伝播して来たか、横方向の座標をメモ
    }
    for (ll direction = 4; direction < 8; ++direction) {
      ll next_x = x + dx[direction];
      ll next_y = y + dy[direction];
      if (next_x < 0 || next_x >= H || next_y < 0 || next_y >= W)
        continue; // 場外アウトならダメ
      if (field[next_x][next_y] == '#')
        continue; // 壁はダメ
      d = dist[x][y] + 1;
      // まだ見ていない頂点なら push
      if (dist[next_x][next_y] == -1) {
        que.push_back(make_pair(next_x, next_y));
        dist[next_x][next_y] = dist[x][y] + 1;
      } else if (dist[next_x][next_y] > d) {
        que.push_back(make_pair(next_x, next_y));
        dist[next_x][next_y] = dist[x][y] + 1;
      }
    }
    for (ll direction = 0; direction < 4; ++direction) {
      ll next_x = x + 2 * dx[direction];
      ll next_y = y + 2 * dy[direction];
      if (next_x < 0 || next_x >= H || next_y < 0 || next_y >= W)
        continue; // 場外アウトならダメ
      if (field[next_x][next_y] == '#')
        continue; // 壁はダメ

      if (dist[next_x][next_y] == -1) {
        que.push_back(make_pair(next_x, next_y));
        dist[next_x][next_y] = dist[x][y] + 1;
      } else if (dist[next_x][next_y] > d) {
        que.push_back(make_pair(next_x, next_y));
        dist[next_x][next_y] = dist[x][y] + 1;
      }
    }
    for (ll direction = 4; direction < 8; ++direction) {
      ll next_x = x + 2 * dx[direction];
      ll next_y = y + 2 * dy[direction];
      if (next_x < 0 || next_x >= H || next_y < 0 || next_y >= W)
        continue; // 場外アウトならダメ
      if (field[next_x][next_y] == '#')
        continue; // 壁はダメ

      if (dist[next_x][next_y] == -1) {
        que.push_back(make_pair(next_x, next_y));
        dist[next_x][next_y] = dist[x][y] + 1;
      } else if (dist[next_x][next_y] > d) {
        que.push_back(make_pair(next_x, next_y));
        dist[next_x][next_y] = dist[x][y] + 1;
      }
    }
    for (ll direction = 4; direction < 8; ++direction) {
      ll next_x = x + 2 * dx[direction];
      ll next_y = y + dy[direction];
      if (next_x < 0 || next_x >= H || next_y < 0 || next_y >= W)
        continue; // 場外アウトならダメ
      if (field[next_x][next_y] == '#')
        continue; // 壁はダメ

      if (dist[next_x][next_y] == -1) {
        que.push_back(make_pair(next_x, next_y));
        dist[next_x][next_y] = dist[x][y] + 1;
      } else if (dist[next_x][next_y] > d) {
        que.push_back(make_pair(next_x, next_y));
        dist[next_x][next_y] = dist[x][y] + 1;
      }
    }
    for (ll direction = 4; direction < 8; ++direction) {
      ll next_x = x + dx[direction];
      ll next_y = y + 2 * dy[direction];
      if (next_x < 0 || next_x >= H || next_y < 0 || next_y >= W)
        continue; // 場外アウトならダメ
      if (field[next_x][next_y] == '#')
        continue; // 壁はダメ

      if (dist[next_x][next_y] == -1) {
        que.push_back(make_pair(next_x, next_y));
        dist[next_x][next_y] = dist[x][y] + 1;
      } else if (dist[next_x][next_y] > d) {
        que.push_back(make_pair(next_x, next_y));
        dist[next_x][next_y] = dist[x][y] + 1;
      }
    }
  }
  cout << dist[gx][gy] << endl;
}