Problem p02579 (C++)

Buggy submission (status: Runtime Error):
#include <bits/stdc++.h>
using namespace std;

typedef long long ll;
typedef pair<int, int> P;
typedef pair<ll, ll> PL;
#define int ll

const ll MOD = 1000000007;
const ll INF_LL = (ll)1000000007 * 1000000007;
const int INF_INT = (int)1000000007;
const double PI = 3.14159265358979323846;

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

const int dx2[20] = {2, 2,  2,  2,  2,  1,  1,  1,  1,  0,
                     0, -1, -1, -1, -1, -2, -2, -2, -2, -2};
const int dy2[20] = {-2, -1, 0,  1, 2, -2, -1, 1, 2, -2,
                     2,  -2, -1, 1, 2, -2, -1, 0, 1, 2};

#define FOR(i, a, b) for (int i = (a); i < (b); ++i)
#define rep(i, n) FOR(i, 0, n)
#define rrep(i, n) for (int i = ((int)(n)-1); i >= 0; i--)
#define irep(itr, st) for (auto itr = (st).begin(); itr != (st).end(); ++itr)
#define irrep(itr, st) for (auto itr = (st).rbegin(); itr != (st).rend(); ++itr)

#define m0(x) memset((x), 0, sizeof((x)))
#define m1(x) memset((x), -1, sizeof((x)))

// xにはvectorなどのコンテナ
#define ALL(x) (x).begin(), (x).end() // sortなどの引数を省略したい
#define RALL(x) (x).rbegin(), (x).rend() // sortなどの引数を省略したい
#define SIZE(x) ((ll)(x).size())    // sizeをsize_tからllに直しておく
#define MAX(x) *max_element(ALL(x)) // 最大値を求める
#define MIN(x) *min_element(ALL(x)) // 最小値を求める
#define all(x) (x).begin(), (x).end()

// 略記
#define pb emplace_back // vectorヘの挿入
#define mp make_pair    // pairのコンストラクタ
#define F first         // pairの一つ目の要素
#define S second        // pairの二つ目の要素

#define BITCOUNT __builtin_popcount
#define BITCOUNT_LL(x) __builtin_popcountll(x)

#define perm(c)                                                                \
  sort(all(c));                                                                \
  for (bool c##p = 1; c##p;                                                    \
       c##p = next_permutation(all(c))) // 順列 123 132 213 231 312 321

#define BIT(n) (1LL << (n))

#ifdef DEBUG
#define PRINT(A) std::cout << (#A) << ": " << (A) << std::endl;
#else
#define PRINT(A)
#endif

// 入力高速化
struct IoSetup {
  IoSetup() {
    cin.tie(nullptr);
    ios::sync_with_stdio(false);
    cout << fixed << setprecision(20);
  }
} iosetup;

template <class T> inline bool chmin(T &a, T b) {
  if (a > b) {
    a = b;
    return true;
  }
  return false;
}

template <class T> inline bool chmax(T &a, T b) {
  if (a < b) {
    a = b;
    return true;
  }
  return false;
}

// ダイクストラ
// 単一始点最短路問題

struct Edge {
  int to;
  int cost;
  Edge(int a, int b) {
    to = a;
    cost = b;
  }
};

int H, W;

int Ch, Cw, Dh, Dw;
vector<string> S(100);

// sに行先を入れると、dist[to]にコストが入ります

const ll MAX_NODE_COUNT = 1000000; // nodeの最大数 更新必要 CINなどで更新でも可
vector<ll> dist;
vector<Edge> edge;

void dijkstra(int s) {
  // greater<P>
  // の指定で、Pを小さい順に取り出せる。P.firstに距離やコストを入れておけばOK。
  priority_queue<P, vector<P>, greater<P>> que;
  dist.assign(
      H * W + 5,
      INF_LL); // 本当は+5いらないけど、nodeが0ではなく1～の時ように余裕もたせておく。
  dist[s] = 0;
  que.push(P(0, s));

  while (!que.empty()) {
    // 現時点で一番低コストになっているQueを読み込む
    P p = que.top();
    que.pop();
    // 現在見てる頂点番号を確認する
    int v = p.second;
    // 過去の最低コストを確認し、現在のコストより低コストの時点で探索済みだったら帰る。
    if (dist[v] < p.first)
      continue;

    rep(i, 4) {
      // 今のNodeからいける範囲で、値を更新できそうなところをQueに入れとく。
      int nowX = v % W;
      int nowY = v / W;

      int distX = nowX + dx[i];
      int distY = nowY + dy[i];

      if (distX < 0 || distX >= W || distY < 0 || distY >= H)
        continue;
      if (S[distY][distX] == '#')
        continue;

      if (dist[distX + distY * W] > dist[v]) {
        dist[distX + distY * W] = dist[v];
        que.push(P(dist[distX + distY * W], distX + distY * W));
      }
    }

    rep(i, 20) {
      // 今のNodeからいける範囲で、値を更新できそうなところをQueに入れとく。
      int nowX = v % W;
      int nowY = v / W;

      int distX = nowX + dx2[i];
      int distY = nowY + dy2[i];

      if (distX < 0 || distX >= W || distY < 0 || distY >= H)
        continue;
      if (S[distY][distX] == '#')
        continue;

      if (dist[distX + distY * W] > dist[v] + 1) {
        dist[distX + distY * W] = dist[v] + 1;
        que.push(P(dist[distX + distY * W], distX + distY * W));
      }
    }
  }
}

signed main() {
  cin >> H >> W;
  cin >> Ch >> Cw >> Dh >> Dw;

  Ch--;
  Cw--;
  Dh--;
  Dw--;

  rep(i, H) { cin >> S[i]; }

  dijkstra(W * Ch + Cw);

  if (dist[Dh * W + Dw] == INF_LL)
    dist[Dh * W + Dw] = -1;
  cout << dist[Dh * W + Dw] << endl;
}

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

typedef long long ll;
typedef pair<int, int> P;
typedef pair<ll, ll> PL;
#define int ll

const ll MOD = 1000000007;
const ll INF_LL = (ll)1000000007 * 1000000007;
const int INF_INT = (int)1000000007;
const double PI = 3.14159265358979323846;

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

const int dx2[20] = {2, 2,  2,  2,  2,  1,  1,  1,  1,  0,
                     0, -1, -1, -1, -1, -2, -2, -2, -2, -2};
const int dy2[20] = {-2, -1, 0,  1, 2, -2, -1, 1, 2, -2,
                     2,  -2, -1, 1, 2, -2, -1, 0, 1, 2};

#define FOR(i, a, b) for (int i = (a); i < (b); ++i)
#define rep(i, n) FOR(i, 0, n)
#define rrep(i, n) for (int i = ((int)(n)-1); i >= 0; i--)
#define irep(itr, st) for (auto itr = (st).begin(); itr != (st).end(); ++itr)
#define irrep(itr, st) for (auto itr = (st).rbegin(); itr != (st).rend(); ++itr)

#define m0(x) memset((x), 0, sizeof((x)))
#define m1(x) memset((x), -1, sizeof((x)))

// xにはvectorなどのコンテナ
#define ALL(x) (x).begin(), (x).end() // sortなどの引数を省略したい
#define RALL(x) (x).rbegin(), (x).rend() // sortなどの引数を省略したい
#define SIZE(x) ((ll)(x).size())    // sizeをsize_tからllに直しておく
#define MAX(x) *max_element(ALL(x)) // 最大値を求める
#define MIN(x) *min_element(ALL(x)) // 最小値を求める
#define all(x) (x).begin(), (x).end()

// 略記
#define pb emplace_back // vectorヘの挿入
#define mp make_pair    // pairのコンストラクタ
#define F first         // pairの一つ目の要素
#define S second        // pairの二つ目の要素

#define BITCOUNT __builtin_popcount
#define BITCOUNT_LL(x) __builtin_popcountll(x)

#define perm(c)                                                                \
  sort(all(c));                                                                \
  for (bool c##p = 1; c##p;                                                    \
       c##p = next_permutation(all(c))) // 順列 123 132 213 231 312 321

#define BIT(n) (1LL << (n))

#ifdef DEBUG
#define PRINT(A) std::cout << (#A) << ": " << (A) << std::endl;
#else
#define PRINT(A)
#endif

// 入力高速化
struct IoSetup {
  IoSetup() {
    cin.tie(nullptr);
    ios::sync_with_stdio(false);
    cout << fixed << setprecision(20);
  }
} iosetup;

template <class T> inline bool chmin(T &a, T b) {
  if (a > b) {
    a = b;
    return true;
  }
  return false;
}

template <class T> inline bool chmax(T &a, T b) {
  if (a < b) {
    a = b;
    return true;
  }
  return false;
}

// ダイクストラ
// 単一始点最短路問題

struct Edge {
  int to;
  int cost;
  Edge(int a, int b) {
    to = a;
    cost = b;
  }
};

int H, W;

int Ch, Cw, Dh, Dw;
vector<string> S(10000);

// sに行先を入れると、dist[to]にコストが入ります

const ll MAX_NODE_COUNT = 1000000; // nodeの最大数 更新必要 CINなどで更新でも可
vector<ll> dist;
vector<Edge> edge;

void dijkstra(int s) {
  // greater<P>
  // の指定で、Pを小さい順に取り出せる。P.firstに距離やコストを入れておけばOK。
  priority_queue<P, vector<P>, greater<P>> que;
  dist.assign(
      H * W + 5,
      INF_LL); // 本当は+5いらないけど、nodeが0ではなく1～の時ように余裕もたせておく。
  dist[s] = 0;
  que.push(P(0, s));

  while (!que.empty()) {
    // 現時点で一番低コストになっているQueを読み込む
    P p = que.top();
    que.pop();
    // 現在見てる頂点番号を確認する
    int v = p.second;
    // 過去の最低コストを確認し、現在のコストより低コストの時点で探索済みだったら帰る。
    if (dist[v] < p.first)
      continue;

    rep(i, 4) {
      // 今のNodeからいける範囲で、値を更新できそうなところをQueに入れとく。
      int nowX = v % W;
      int nowY = v / W;

      int distX = nowX + dx[i];
      int distY = nowY + dy[i];

      if (distX < 0 || distX >= W || distY < 0 || distY >= H)
        continue;
      if (S[distY][distX] == '#')
        continue;

      if (dist[distX + distY * W] > dist[v]) {
        dist[distX + distY * W] = dist[v];
        que.push(P(dist[distX + distY * W], distX + distY * W));
      }
    }

    rep(i, 20) {
      // 今のNodeからいける範囲で、値を更新できそうなところをQueに入れとく。
      int nowX = v % W;
      int nowY = v / W;

      int distX = nowX + dx2[i];
      int distY = nowY + dy2[i];

      if (distX < 0 || distX >= W || distY < 0 || distY >= H)
        continue;
      if (S[distY][distX] == '#')
        continue;

      if (dist[distX + distY * W] > dist[v] + 1) {
        dist[distX + distY * W] = dist[v] + 1;
        que.push(P(dist[distX + distY * W], distX + distY * W));
      }
    }
  }
}

signed main() {
  cin >> H >> W;
  cin >> Ch >> Cw >> Dh >> Dw;

  Ch--;
  Cw--;
  Dh--;
  Dw--;

  rep(i, H) { cin >> S[i]; }

  dijkstra(W * Ch + Cw);

  if (dist[Dh * W + Dw] == INF_LL)
    dist[Dh * W + Dw] = -1;
  cout << dist[Dh * W + Dw] << endl;
}