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


// #pragma GCC optimize ("-O3")
#include <algorithm>
#include <array>
#include <bitset>
#include <cassert>
#include <cmath>
#include <complex>
#include <cstdio>
#include <functional>
#include <iomanip>
#include <iostream>
#include <list>
#include <map>
#include <numeric>
#include <queue>
#include <random>
#include <regex>
#include <set>
#include <sstream>
#include <stack>
#include <string>
#include <time.h>
#include <type_traits>
#include <typeinfo>
#include <unordered_map>
#include <vector>
#ifdef _MSC_VER
#include <intrin.h>
#define popcnt __popcnt64
// #  define __builtin_popcount __popcnt
#else
#define popcnt __builtin_popcountll
#endif
// #include "boost/variant.hpp"

// #include <boost/multiprecision/cpp_int.hpp>
// namespace mp = boost::multiprecision;
// using lll = mp::cpp_int;

using namespace std;

typedef long long ll;
constexpr ll MOD = 1000000007ll;
constexpr ll INF = 1LL << 60;

#define rep(i, N, M) for (ll i = N, i##_len = (M); i < i##_len; ++i)
#define rep_skip(i, N, M, ...)                                                 \\
  for (ll i = N, i##_len = (M); i < i##_len; i += (skip))
#define rrep(i, N, M) for (ll i = (M)-1, i##_len = (N - 1); i > i##_len; --i)
#define repbit(bit, N, DIG) rep(bit, (N), (1LL << (DIG)))
#define pb push_back
#define fir first
#define sec second
#define all(a) (a).begin(), (a).end()
#define rall(a) (a).rbegin(), (a).rend()
#define perm(c)                                                                \\
  sort(all(c));                                                                \\
  for (bool c##perm = 1; c##perm;                                              \\
       c##perm = next_permutation(                                             \\
           all(c))) // perm(c){write(c)} writes all permutation of c
constexpr ll dceil(ll x, ll y) {
  if (y < 0) {
    x *= -1;
    y *= -1;
  };
  return x > 0 ? (x + y - 1) / y : x / y;
} // ceil for x/y
constexpr ll dfloor(ll x, ll y) {
  if (y < 0) {
    x *= -1;
    y *= -1;
  };
  return x > 0 ? x / y : -dceil((-x), y);
} // floor for x/y

typedef pair<double, double> pd;
typedef pair<ll, ll> pll;
typedef vector<ll> vll;
typedef vector<vll> vvll;
typedef vector<pll> vpll;
typedef vector<bool> vb;
typedef vector<vb> vvb;
typedef vector<string> vs;
template <typename T>
using pq_greater = priority_queue<T, vector<T>, greater<T>>;
template <typename T> using vpt = vector<complex<T>>;

template <int n> struct tll_impl {
  using type = decltype(tuple_cat(tuple<ll>(),
                                  declval<typename tll_impl<n - 1>::type>()));
};
template <> struct tll_impl<1> {
  using type = tuple<ll>;
};
template <int n> using tll = typename tll_impl<n>::type;

template <class T> constexpr ll SZ(T &v) { return static_cast<ll>(v.size()); };

template <int n, typename T> struct vec_t_impl {
  using type = vector<typename vec_t_impl<n - 1, T>::type>;
};
template <typename T> struct vec_t_impl<1, T> {
  using type = vector<T>;
};
template <int n, typename T> using vec_t = typename vec_t_impl<n, T>::type;
// check
static_assert(is_same<vec_t<3, ll>, vector<vector<vector<ll>>>>::value, "");

// decompose vector into basetype and dimension.
template <typename T> struct vec_dec {
  static constexpr int dim = 0;
  using type = T;
};
template <typename T> struct vec_dec<vector<T>> {
  static constexpr int dim = vec_dec<T>::dim + 1;
  using type = typename vec_dec<T>::type;
};
static_assert(is_same<typename vec_dec<vec_t<3, ll>>::type, ll>::value, "");
static_assert(vec_dec<vec_t<3, ll>>::dim == 3, "");

template <typename T = ll> vector<T> makev(size_t a) { return vector<T>(a); }

template <typename T = ll, typename... Ts> auto makev(size_t a, Ts... ts) {
  return vector<decltype(makev<T>(ts...))>(a, makev<T>(ts...));
} // ex:  auto dp =  makev<ll>(4,5) => vector<vector<ll>> dp(4,vector<ll>(5));

template <typename T>
struct is_vector : std::false_type {}; // check if T is vector

template <typename T> struct is_vector<vector<T>> : std::true_type {};
static_assert(is_vector<vector<ll>>::value == true &&
                  is_vector<ll>::value == false,
              "");

// check if T is vector
template <typename T> struct is_pair : std::false_type {};

template <typename T, typename S>
struct is_pair<pair<T, S>> : std::true_type {};
static_assert(is_pair<pll>::value == true && is_pair<ll>::value == false, "");

template <typename T, typename V,
          typename enable_if<!is_vector<T>::value, nullptr_t>::type = nullptr>
void fill_v(T &t, const V &v) {
  t = v;
}

template <typename T, typename V,
          typename enable_if<is_vector<T>::value, nullptr_t>::type = nullptr>
void fill_v(T &t, const V &v) {
  for (auto &&x : t)
    fill_v(x, v);
} // ex:  fill_v(dp, INF);

namespace std {
template <class T> bool operator<(const complex<T> &a, const complex<T> &b) {
  return a.real() == b.real() ? a.imag() < b.imag() : a.real() < b.real();
}
}; // namespace std

template <typename T, typename S>
istream &operator>>(istream &istr, pair<T, S> &x) {
  return istr >> x.first >> x.second;
}
template <typename T> istream &operator>>(istream &istr, vector<T> &x) {
  rep(i, 0, x.size()) istr >> x[i];
  return istr;
}
template <typename T> istream &operator>>(istream &istr, complex<T> &x) {
  T r, i;
  istr >> r >> i;
  x.real(r);
  x.imag(i);
  return istr;
}

template <typename T, typename Delim_t = string,
          typename enable_if<!is_vector<T>::value, nullptr_t>::type = nullptr>
void write(T &x, Delim_t delim = " ") {
  cout << x << delim;
}
template <typename T, typename Delim_t = string,
          typename enable_if<is_vector<T>::value, nullptr_t>::type = nullptr>
void write(T &x, Delim_t delim = " ") {
  rep(i, 0, x.size()) write(x[i], (i == (x.size() - 1) ? "" : delim));
  cout << '\\n';
}

template <typename T> void chmin(T &a, T b) {
  if (a > b)
    a = b;
}
template <typename T> void chmax(T &a, T b) {
  if (a < b)
    a = b;
}

vll seq(ll i, ll j) {
  vll res(j - i);
  rep(k, i, j) res[k] = i + k;
  return res;
}

constexpr ll POW_0(ll x, ll y) {
  if (y == 0)
    return 1;
  if (y == 1)
    return x;
  if (y == 2)
    return x * x;
  if (y % 2 == 0)
    return POW_0(POW_0(x, y / 2), 2LL);
  return ((POW_0(POW_0(x, y / 2), 2LL)) * (x));
}

constexpr ll POW(ll x, ll y, ll mod = 0) {
  if (mod == 0)
    return POW_0(x, y);
  if (y == 0)
    return 1;
  if (y == 1)
    return x % mod;
  if (y == 2)
    return x * x % mod;
  if (y % 2 == 0)
    return POW(POW(x, y / 2, mod), 2LL, mod) % mod;
  return ((POW(POW(x, y / 2, mod), 2LL, mod)) * (x % mod)) % mod;
}

template <typename Inputs, typename Functor,
          typename T = typename Inputs::value_type>
void sort_by(Inputs &inputs, Functor f) {
  std::sort(std::begin(inputs), std::end(inputs),
            [&f](const T &lhs, const T &rhs) { return f(lhs) < f(rhs); });
}

template <int pos, typename Inputs, typename T = typename Inputs::value_type>
void sort_by(Inputs &inputs) {
  std::sort(
      std::begin(inputs), std::end(inputs),
      [](const T &lhs, const T &rhs) { return get<pos>(lhs) < get<pos>(rhs); });
}

template <typename Inputs, typename Functor,
          typename T = typename Inputs::value_type>
void stable_sort_by(Inputs &inputs, Functor f) {
  std::stable_sort(
      std::begin(inputs), std::end(inputs),
      [&f](const T &lhs, const T &rhs) { return f(lhs) < f(rhs); });
}

template <typename Inputs> void sort_uniq(Inputs &inputs) {
  sort(all(inputs));
  inputs.erase(unique(all(inputs)), inputs.end());
}

vector<string> split(const string &s, char delim) {
  vector<string> elems;
  stringstream ss(s);
  string item;
  if (s.size() > 0 && s.front() == delim) {
    elems.push_back("");
  }
  while (getline(ss, item, delim)) {
    if (!item.empty()) {
      elems.push_back(item);
    }
  }
  if (s.size() > 0 && s.back() == delim) {
    elems.push_back("");
  }
  return elems;
}

template <class T> map<T, ll> inv_map(vector<T> &x) {
  map<T, ll> res;
  rep(i, 0, x.size()) { res[x[i]] = i; }
  return res;
}
template <class K, class V> map<V, K> inv_map(map<K, V> &m) {
  map<V, K> res;
  for (const auto &x : m) {
    res[x.second] = x.first;
  }
  return res;
}
template <class T, class val_t = typename T::value_type,
          enable_if_t<!is_same<T, set<val_t>>::value> * = nullptr>
constexpr bool exist(const T &container, val_t val) {
  return find(all(container), val) != container.end();
}
template <class T, class val_t = typename T::value_type,
          enable_if_t<is_same<T, set<val_t>>::value> * = nullptr>
constexpr bool exist(const T &container, val_t val) {
  return container.find(val) != container.end();
}

// inner prod: |a||b|cos(theta)
template <class T> T dot(complex<T> a, complex<T> b) {
  return a.real() * b.real() + a.imag() * b.imag();
}
// outer prod |a||b|sin(theta)
template <class T> T cross(complex<T> a, complex<T> b) {
  return a.real() * b.imag() - a.imag() * b.real();
}

struct D2 {
  enum Dir { U, D, L, R };
  static inline vector<Dir> Dirs = {U, D, L, R};
  D2(ll h, ll w) : h(h), w(w){};
  bool in(ll n, D2::Dir d, ll k = 1) {
    if ((W(n) <= k - 1) && d == L)
      return false;
    if ((W(n) >= w - 1 - (k - 1)) && d == R)
      return false;
    if ((H(n) <= k - 1) && d == D)
      return false;
    if ((H(n) >= h - 1 - (k - 1)) && d == U)
      return false;
    return true;
  };
  ll next(Dir d, ll k = 1) {
    switch (d) {
    case U:
      return w * k;
    case D:
      return -w * k;
    case L:
      return -k;
    case R:
      return k;
    default:
      throw invalid_argument("not direction");
    }
  }
  ll H(ll n) { return n / w; }
  ll W(ll n) { return n % w; }

  ll h, w;
};

int main() {

  cin.tie(0);
  cout.tie(0);
  ios::sync_with_stdio(false);
  cout << fixed << setprecision(12);

  ll h, w;
  cin >> h >> w;
  // ll h = 1000, w = 1000;
  D2 d2(h, w);
  pll cc, dd;
  cin >> cc >> dd;
  // pll cc{ 1,1 }, dd{ 999,999 };
  ll c = (cc.first - 1) * w + (cc.second - 1);
  ll d = (dd.first - 1) * w + (dd.second - 1);
  vs SS(h);
  cin >> SS;
  // vs SS(h, string(1000, '.'));

  string S;
  rep(i, 0, h) { S.insert(S.end(), all(SS[i])); }

  ll N = h * w;
  vll stack1;
  vll memo(N, INF);
  memo[c] = 0;
  stack1.push_back(c);
  auto up = [&](ll cur, ll next, ll shift) {
    if (memo[cur] + shift < memo[next]) {
      memo[next] = memo[cur] + shift;
    }
  };
  while (stack1.size()) {
    vll stack2;
    while (stack1.size()) {
      ll cur = stack1.back();
      stack1.pop_back();
      stack2.push_back(cur);
      for (auto di : d2.Dirs) {
        if (d2.in(cur, di)) {
          ll next = cur + d2.next(di);
          if (S[next] == '.') {
            if (memo[cur] < memo[next]) {
              stack1.push_back(next);
              stack2.push_back(next);
              memo[next] = memo[cur];
            }
          }
        }
      }
    }
    while (stack2.size()) {
      ll cur = stack2.back();
      stack2.pop_back();
      for (auto di1 : d2.Dirs) {
        for (auto di2 : d2.Dirs) {
          if ((int)di1 >= (int)di2)
            continue;
          rep(l1, 0, 3) {
            rep(l2, 0, 3) {
              if (d2.in(cur, di1, l1)) {
                ll next1 = cur + d2.next(di1, l1);
                if (d2.in(next1, di2, l2)) {
                  ll next = next1 + d2.next(di2, l2);
                  if (cur != next && S[next] == '.') {
                    if (memo[cur] + 1 < memo[next]) {
                      stack1.push_back(next);
                      memo[next] = memo[cur] + 1;
                    }
                  }
                }
              }
            }
          }
        }
      }
    }
  }
  cout << (memo[d] == INF ? -1 : memo[d]) << endl;

  return 0;
}


Error: TLE

Fixed submission:


// #pragma GCC optimize ("-O3")
#include <algorithm>
#include <array>
#include <bitset>
#include <cassert>
#include <cmath>
#include <complex>
#include <cstdio>
#include <functional>
#include <iomanip>
#include <iostream>
#include <list>
#include <map>
#include <numeric>
#include <queue>
#include <random>
#include <regex>
#include <set>
#include <sstream>
#include <stack>
#include <string>
#include <time.h>
#include <type_traits>
#include <typeinfo>
#include <unordered_map>
#include <vector>
#ifdef _MSC_VER
#include <intrin.h>
#define popcnt __popcnt64
// #  define __builtin_popcount __popcnt
#else
#define popcnt __builtin_popcountll
#endif
// #include "boost/variant.hpp"

// #include <boost/multiprecision/cpp_int.hpp>
// namespace mp = boost::multiprecision;
// using lll = mp::cpp_int;

using namespace std;

typedef long long ll;
constexpr ll MOD = 1000000007ll;
constexpr ll INF = 1LL << 60;

#define rep(i, N, M) for (ll i = N, i##_len = (M); i < i##_len; ++i)
#define rep_skip(i, N, M, ...)                                                 \\
  for (ll i = N, i##_len = (M); i < i##_len; i += (skip))
#define rrep(i, N, M) for (ll i = (M)-1, i##_len = (N - 1); i > i##_len; --i)
#define repbit(bit, N, DIG) rep(bit, (N), (1LL << (DIG)))
#define pb push_back
#define fir first
#define sec second
#define all(a) (a).begin(), (a).end()
#define rall(a) (a).rbegin(), (a).rend()
#define perm(c)                                                                \\
  sort(all(c));                                                                \\
  for (bool c##perm = 1; c##perm;                                              \\
       c##perm = next_permutation(                                             \\
           all(c))) // perm(c){write(c)} writes all permutation of c
constexpr ll dceil(ll x, ll y) {
  if (y < 0) {
    x *= -1;
    y *= -1;
  };
  return x > 0 ? (x + y - 1) / y : x / y;
} // ceil for x/y
constexpr ll dfloor(ll x, ll y) {
  if (y < 0) {
    x *= -1;
    y *= -1;
  };
  return x > 0 ? x / y : -dceil((-x), y);
} // floor for x/y

typedef pair<double, double> pd;
typedef pair<ll, ll> pll;
typedef vector<ll> vll;
typedef vector<vll> vvll;
typedef vector<pll> vpll;
typedef vector<bool> vb;
typedef vector<vb> vvb;
typedef vector<string> vs;
template <typename T>
using pq_greater = priority_queue<T, vector<T>, greater<T>>;
template <typename T> using vpt = vector<complex<T>>;

template <int n> struct tll_impl {
  using type = decltype(tuple_cat(tuple<ll>(),
                                  declval<typename tll_impl<n - 1>::type>()));
};
template <> struct tll_impl<1> {
  using type = tuple<ll>;
};
template <int n> using tll = typename tll_impl<n>::type;

template <class T> constexpr ll SZ(T &v) { return static_cast<ll>(v.size()); };

template <int n, typename T> struct vec_t_impl {
  using type = vector<typename vec_t_impl<n - 1, T>::type>;
};
template <typename T> struct vec_t_impl<1, T> {
  using type = vector<T>;
};
template <int n, typename T> using vec_t = typename vec_t_impl<n, T>::type;
// check
static_assert(is_same<vec_t<3, ll>, vector<vector<vector<ll>>>>::value, "");

// decompose vector into basetype and dimension.
template <typename T> struct vec_dec {
  static constexpr int dim = 0;
  using type = T;
};
template <typename T> struct vec_dec<vector<T>> {
  static constexpr int dim = vec_dec<T>::dim + 1;
  using type = typename vec_dec<T>::type;
};
static_assert(is_same<typename vec_dec<vec_t<3, ll>>::type, ll>::value, "");
static_assert(vec_dec<vec_t<3, ll>>::dim == 3, "");

template <typename T = ll> vector<T> makev(size_t a) { return vector<T>(a); }

template <typename T = ll, typename... Ts> auto makev(size_t a, Ts... ts) {
  return vector<decltype(makev<T>(ts...))>(a, makev<T>(ts...));
} // ex:  auto dp =  makev<ll>(4,5) => vector<vector<ll>> dp(4,vector<ll>(5));

template <typename T>
struct is_vector : std::false_type {}; // check if T is vector

template <typename T> struct is_vector<vector<T>> : std::true_type {};
static_assert(is_vector<vector<ll>>::value == true &&
                  is_vector<ll>::value == false,
              "");

// check if T is vector
template <typename T> struct is_pair : std::false_type {};

template <typename T, typename S>
struct is_pair<pair<T, S>> : std::true_type {};
static_assert(is_pair<pll>::value == true && is_pair<ll>::value == false, "");

template <typename T, typename V,
          typename enable_if<!is_vector<T>::value, nullptr_t>::type = nullptr>
void fill_v(T &t, const V &v) {
  t = v;
}

template <typename T, typename V,
          typename enable_if<is_vector<T>::value, nullptr_t>::type = nullptr>
void fill_v(T &t, const V &v) {
  for (auto &&x : t)
    fill_v(x, v);
} // ex:  fill_v(dp, INF);

namespace std {
template <class T> bool operator<(const complex<T> &a, const complex<T> &b) {
  return a.real() == b.real() ? a.imag() < b.imag() : a.real() < b.real();
}
}; // namespace std

template <typename T, typename S>
istream &operator>>(istream &istr, pair<T, S> &x) {
  return istr >> x.first >> x.second;
}
template <typename T> istream &operator>>(istream &istr, vector<T> &x) {
  rep(i, 0, x.size()) istr >> x[i];
  return istr;
}
template <typename T> istream &operator>>(istream &istr, complex<T> &x) {
  T r, i;
  istr >> r >> i;
  x.real(r);
  x.imag(i);
  return istr;
}

template <typename T, typename Delim_t = string,
          typename enable_if<!is_vector<T>::value, nullptr_t>::type = nullptr>
void write(T &x, Delim_t delim = " ") {
  cout << x << delim;
}
template <typename T, typename Delim_t = string,
          typename enable_if<is_vector<T>::value, nullptr_t>::type = nullptr>
void write(T &x, Delim_t delim = " ") {
  rep(i, 0, x.size()) write(x[i], (i == (x.size() - 1) ? "" : delim));
  cout << '\\n';
}

template <typename T> void chmin(T &a, T b) {
  if (a > b)
    a = b;
}
template <typename T> void chmax(T &a, T b) {
  if (a < b)
    a = b;
}

vll seq(ll i, ll j) {
  vll res(j - i);
  rep(k, i, j) res[k] = i + k;
  return res;
}

constexpr ll POW_0(ll x, ll y) {
  if (y == 0)
    return 1;
  if (y == 1)
    return x;
  if (y == 2)
    return x * x;
  if (y % 2 == 0)
    return POW_0(POW_0(x, y / 2), 2LL);
  return ((POW_0(POW_0(x, y / 2), 2LL)) * (x));
}

constexpr ll POW(ll x, ll y, ll mod = 0) {
  if (mod == 0)
    return POW_0(x, y);
  if (y == 0)
    return 1;
  if (y == 1)
    return x % mod;
  if (y == 2)
    return x * x % mod;
  if (y % 2 == 0)
    return POW(POW(x, y / 2, mod), 2LL, mod) % mod;
  return ((POW(POW(x, y / 2, mod), 2LL, mod)) * (x % mod)) % mod;
}

template <typename Inputs, typename Functor,
          typename T = typename Inputs::value_type>
void sort_by(Inputs &inputs, Functor f) {
  std::sort(std::begin(inputs), std::end(inputs),
            [&f](const T &lhs, const T &rhs) { return f(lhs) < f(rhs); });
}

template <int pos, typename Inputs, typename T = typename Inputs::value_type>
void sort_by(Inputs &inputs) {
  std::sort(
      std::begin(inputs), std::end(inputs),
      [](const T &lhs, const T &rhs) { return get<pos>(lhs) < get<pos>(rhs); });
}

template <typename Inputs, typename Functor,
          typename T = typename Inputs::value_type>
void stable_sort_by(Inputs &inputs, Functor f) {
  std::stable_sort(
      std::begin(inputs), std::end(inputs),
      [&f](const T &lhs, const T &rhs) { return f(lhs) < f(rhs); });
}

template <typename Inputs> void sort_uniq(Inputs &inputs) {
  sort(all(inputs));
  inputs.erase(unique(all(inputs)), inputs.end());
}

vector<string> split(const string &s, char delim) {
  vector<string> elems;
  stringstream ss(s);
  string item;
  if (s.size() > 0 && s.front() == delim) {
    elems.push_back("");
  }
  while (getline(ss, item, delim)) {
    if (!item.empty()) {
      elems.push_back(item);
    }
  }
  if (s.size() > 0 && s.back() == delim) {
    elems.push_back("");
  }
  return elems;
}

template <class T> map<T, ll> inv_map(vector<T> &x) {
  map<T, ll> res;
  rep(i, 0, x.size()) { res[x[i]] = i; }
  return res;
}
template <class K, class V> map<V, K> inv_map(map<K, V> &m) {
  map<V, K> res;
  for (const auto &x : m) {
    res[x.second] = x.first;
  }
  return res;
}
template <class T, class val_t = typename T::value_type,
          enable_if_t<!is_same<T, set<val_t>>::value> * = nullptr>
constexpr bool exist(const T &container, val_t val) {
  return find(all(container), val) != container.end();
}
template <class T, class val_t = typename T::value_type,
          enable_if_t<is_same<T, set<val_t>>::value> * = nullptr>
constexpr bool exist(const T &container, val_t val) {
  return container.find(val) != container.end();
}

// inner prod: |a||b|cos(theta)
template <class T> T dot(complex<T> a, complex<T> b) {
  return a.real() * b.real() + a.imag() * b.imag();
}
// outer prod |a||b|sin(theta)
template <class T> T cross(complex<T> a, complex<T> b) {
  return a.real() * b.imag() - a.imag() * b.real();
}

struct D2 {
  enum Dir { U, D, L, R };
  static inline vector<Dir> Dirs = {U, D, L, R};
  D2(ll h, ll w) : h(h), w(w){};
  bool in(ll n, D2::Dir d, ll k = 1) {
    if ((W(n) <= k - 1) && d == L)
      return false;
    if ((W(n) >= w - 1 - (k - 1)) && d == R)
      return false;
    if ((H(n) <= k - 1) && d == D)
      return false;
    if ((H(n) >= h - 1 - (k - 1)) && d == U)
      return false;
    return true;
  };
  ll next(Dir d, ll k = 1) {
    switch (d) {
    case U:
      return w * k;
    case D:
      return -w * k;
    case L:
      return -k;
    case R:
      return k;
    default:
      throw invalid_argument("not direction");
    }
  }
  ll H(ll n) { return n / w; }
  ll W(ll n) { return n % w; }

  ll h, w;
};

int main() {

  cin.tie(0);
  cout.tie(0);
  ios::sync_with_stdio(false);
  cout << fixed << setprecision(12);

  ll h, w;
  cin >> h >> w;
  // ll h = 1000, w = 1000;
  D2 d2(h, w);
  pll cc, dd;
  cin >> cc >> dd;
  // pll cc{ 1,1 }, dd{ 999,999 };
  ll c = (cc.first - 1) * w + (cc.second - 1);
  ll d = (dd.first - 1) * w + (dd.second - 1);
  vs SS(h);
  cin >> SS;
  // vs SS(h, string(1000, '.'));

  string S;
  rep(i, 0, h) { S.insert(S.end(), all(SS[i])); }

  ll N = h * w;
  vll stack;
  vll memo(N, INF);
  memo[c] = 0;
  stack.push_back(c);
  auto up = [&](ll cur, ll next, ll shift) {
    if (memo[cur] + shift < memo[next]) {
      stack.push_back(next);
      memo[next] = memo[cur] + shift;
    }
  };
  while (stack.size()) {
    ll cur = stack.back();
    stack.pop_back();
    vll stack1(1, cur);
    vll stack2(1, cur);
    while (stack1.size()) {
      ll cur = stack1.back();
      stack1.pop_back();
      for (auto di : d2.Dirs) {
        if (d2.in(cur, di)) {
          ll next = cur + d2.next(di);
          if (S[next] == '.') {
            if (memo[cur] < memo[next]) {
              stack1.push_back(next);
              stack2.push_back(next);
              memo[next] = memo[cur];
            }
          }
        }
      }
    }
    while (stack2.size()) {
      ll cur = stack2.back();
      stack2.pop_back();
      for (auto di1 : d2.Dirs) {
        for (auto di2 : d2.Dirs) {
          if ((int)di1 >= (int)di2)
            continue;
          rep(l1, 0, 3) {
            rep(l2, 0, 3) {
              if (d2.in(cur, di1, l1)) {
                ll next1 = cur + d2.next(di1, l1);
                if (d2.in(next1, di2, l2)) {
                  ll next = next1 + d2.next(di2, l2);
                  if (cur != next && S[next] == '.') {
                    if (memo[cur] + 1 < memo[next]) {
                      stack.push_back(next);
                      memo[next] = memo[cur] + 1;
                    }
                  }
                }
              }
            }
          }
        }
      }
    }
  }
  cout << (memo[d] == INF ? -1 : memo[d]) << endl;

  return 0;
}