Problem p00908 (C++)

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

#define dump(n) cout << "# " << #n << '=' << (n) << endl
#define repi(i, a, b) for (int i = int(a); i < int(b); i++)
#define peri(i, a, b) for (int i = int(b); i-- > int(a);)
#define rep(i, n) repi(i, 0, n)
#define per(i, n) peri(i, 0, n)
#define all(c) begin(c), end(c)
#define mp make_pair
#define mt make_tuple

typedef unsigned int uint;
typedef long long ll;
typedef unsigned long long ull;
typedef pair<int, int> pii;
typedef vector<int> vi;
typedef vector<vi> vvi;
typedef vector<ll> vl;
typedef vector<vl> vvl;
typedef vector<double> vd;
typedef vector<vd> vvd;
typedef vector<string> vs;

const int INF = 1e9;
const int MOD = 1e9 + 7;
const double EPS = 1e-9;

template <typename T1, typename T2>
ostream &operator<<(ostream &os, const pair<T1, T2> &p) {
  return os << '(' << p.first << ',' << p.second << ')';
}
template <typename T> ostream &operator<<(ostream &os, const vector<T> &a) {
  os << '[';
  rep(i, a.size()) os << (i ? " " : "") << a[i];
  return os << ']';
}

typedef vector<vvi> vvvi;
typedef vector<vvvi> vvvvi;

template <typename Functor> struct functor_traits {
  template <typename C, typename Ret, typename Arg, typename... Args>
  static Arg helper(Ret (C::*)(Arg, Args...));
  template <typename C, typename Ret, typename Arg, typename... Args>
  static Arg helper(Ret (C::*)(Arg, Args...) const);
  typedef decltype(helper(&Functor::operator())) first_argument_type;
};
template <typename Compare,
          typename T = typename functor_traits<Compare>::first_argument_type>
priority_queue<T, vector<T>, Compare> make_priority_queue(Compare comp) {
  return priority_queue<T, vector<T>, Compare>(move(comp));
}

bool in(int h, int w, int i, int j) {
  return 0 <= i && i < h && 0 <= j && j < w;
}
bool in(int h, int w, pii p) { return in(h, w, p.first, p.second); }

int calc(vs grid, pii king, pii a, pii b) {
  int h = grid.size(), w = grid[0].size();
  rep(i, 2) rep(j, 2) grid[king.first + i][king.second + j] = '*';
  vvi dist(h, vi(w, INF));
  queue<tuple<int, int, int>> q;
  q.emplace(a.first, a.second, 0);
  while (q.size()) {
    int i, j, d;
    tie(i, j, d) = q.front();
    q.pop();
    if (!in(h, w, i, j) || grid[i][j] == '*' || dist[i][j] != INF)
      continue;
    dist[i][j] = d;
    rep(k, 4) q.emplace(i + "\xff\x1\0\0"[k], j + "\0\0\xff\x1"[k], d + 1);
  }
  return dist[b.first][b.second];
}

int calc(vs grid, pii king, pii p1, pii p2, pii q1, pii q2) {
  return min(calc(grid, king, p1, q1) + calc(grid, king, p2, q2),
             calc(grid, king, p1, q2) + calc(grid, king, p2, q1));
  // int h=grid.size(),w=grid[0].size();
  // rep(i,2) rep(j,2) grid[king.first+i][king.second+j]='*';
  // vvvvi dist(h,vvvi(w,vvi(h,vi(w,INF))));
  // queue<tuple<int,int,int,int,int>> q;
  // q.emplace(p1.first,p1.second,p2.first,p2.second,0);
  // while(q.size()){
  //	int i1,j1,i2,j2,d; tie(i1,j1,i2,j2,d)=q.front(); q.pop();
  //	if(!in(h,w,i1,j1) || !in(h,w,i2,j2) || grid[i1][j1]=='*' ||
  //grid[i2][j2]=='*'
  //	|| (i1==i2 && j1==j2) || dist[i1][j1][i2][j2]!=INF) continue;
  //	dist[i1][j1][i2][j2]=dist[i2][j2][i1][j1]=d;
  //	rep(k,4){
  //		q.emplace(i1+"\xff\x1\0\0"[k],j1+"\0\0\xff\x1"[k],i2,j2,d+1);
  //		q.emplace(i1,j1,i2+"\xff\x1\0\0"[k],j2+"\0\0\xff\x1"[k],d+1);
  //	}
  // }
  // return dist[q1.first][q1.second][q2.first][q2.second];
}

int main() {
  for (int h, w; cin >> h >> w && h | w;) {
    vs grid(h);
    rep(i, h) cin >> grid[i];
    // dump(mp(h,w));
    // rep(i,h) cout<<grid[i]<<endl;

    if (grid[0][0] == 'X') {
      cout << 0 << endl;
      continue;
    }

    auto pq = make_priority_queue(
        [](tuple<int, int, int, int> a, tuple<int, int, int, int> b) {
          return get<3>(a) > get<3>(b);
        });
    {
      pii king(-1, -1), open1(-1, -1), open2(-1, -1);
      rep(i, h) rep(j, w) {
        if (grid[i][j] == 'X') {
          if (king == mp(-1, -1))
            king = mp(i, j);
          grid[i][j] = '.';
        } else if (grid[i][j] == '.')
          (open1 == mp(-1, -1) ? open1 : open2) = mp(i, j);
        else if (grid[i][j] == 'o')
          grid[i][j] = '.';
      }
      int ki = king.first, kj = king.second;
      if (in(h, w, ki - 1, kj) && grid[ki - 1][kj] != '*' &&
          grid[ki - 1][kj + 1] != '*')
        pq.emplace(
            ki, kj, 0,
            calc(grid, king, open1, open2, mp(ki - 1, kj), mp(ki - 1, kj + 1)));
      if (in(h, w, ki + 2, kj) && grid[ki + 2][kj] != '*' &&
          grid[ki + 2][kj + 1] != '*')
        pq.emplace(
            ki, kj, 1,
            calc(grid, king, open1, open2, mp(ki + 2, kj), mp(ki + 2, kj + 1)));
      if (in(h, w, ki, kj - 1) && grid[ki][kj - 1] != '*' &&
          grid[ki + 1][kj - 1] != '*')
        pq.emplace(
            ki, kj, 2,
            calc(grid, king, open1, open2, mp(ki, kj - 1), mp(ki + 1, kj - 1)));
      if (in(h, w, ki, kj + 2) && grid[ki][kj + 2] != '*' &&
          grid[ki + 1][kj + 2] != '*')
        pq.emplace(
            ki, kj, 3,
            calc(grid, king, open1, open2, mp(ki, kj + 2), mp(ki + 1, kj + 2)));
    }

    vvvi dist(h, vvi(w, vi(4, INF)));
    while (pq.size()) {
      // if(rand()%1000==0) printf("> %d\n",pq.size());
      int ki, kj, dir, step;
      tie(ki, kj, dir, step) = pq.top();
      pq.pop();
      if (!in(h, w, ki, kj) || dist[ki][kj][dir] != INF)
        continue;
      dist[ki][kj][dir] = step;
      if (step >= INF)
        break;

      pii open1, open2;
      if (dir == 0)
        open1 = mp(ki - 1, kj), open2 = mp(ki - 1, kj + 1);
      if (dir == 1)
        open1 = mp(ki + 2, kj), open2 = mp(ki + 2, kj + 1);
      if (dir == 2)
        open1 = mp(ki, kj - 1), open2 = mp(ki + 1, kj - 1);
      if (dir == 3)
        open1 = mp(ki, kj + 2), open2 = mp(ki + 1, kj + 2);

      pq.emplace(ki + "\xff\x1\0\0"[dir], kj + "\0\0\xff\x1"[dir], dir ^ 1,
                 step + 1);
      if (in(h, w, ki - 1, kj) && grid[ki - 1][kj] != '*' &&
          grid[ki - 1][kj + 1] != '*')
        pq.emplace(ki, kj, 0,
                   step + calc(grid, mp(ki, kj), open1, open2, mp(ki - 1, kj),
                               mp(ki - 1, kj + 1)));
      if (in(h, w, ki + 2, kj) && grid[ki + 2][kj] != '*' &&
          grid[ki + 2][kj + 1] != '*')
        pq.emplace(ki, kj, 1,
                   step + calc(grid, mp(ki, kj), open1, open2, mp(ki + 2, kj),
                               mp(ki + 2, kj + 1)));
      if (in(h, w, ki, kj - 1) && grid[ki][kj - 1] != '*' &&
          grid[ki + 1][kj - 1] != '*')
        pq.emplace(ki, kj, 2,
                   step + calc(grid, mp(ki, kj), open1, open2, mp(ki, kj - 1),
                               mp(ki + 1, kj - 1)));
      if (in(h, w, ki, kj + 2) && grid[ki][kj + 2] != '*' &&
          grid[ki + 1][kj + 2] != '*')
        pq.emplace(ki, kj, 3,
                   step + calc(grid, mp(ki, kj), open1, open2, mp(ki, kj + 2),
                               mp(ki + 1, kj + 2)));
    }
    int res = *min_element(all(dist[0][0]));
    cout << (res < INF ? res : -1) << endl;
  }
}

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

#define dump(n) cout << "# " << #n << '=' << (n) << endl
#define repi(i, a, b) for (int i = int(a); i < int(b); i++)
#define peri(i, a, b) for (int i = int(b); i-- > int(a);)
#define rep(i, n) repi(i, 0, n)
#define per(i, n) peri(i, 0, n)
#define all(c) begin(c), end(c)
#define mp make_pair
#define mt make_tuple

typedef unsigned int uint;
typedef long long ll;
typedef unsigned long long ull;
typedef pair<int, int> pii;
typedef vector<int> vi;
typedef vector<vi> vvi;
typedef vector<ll> vl;
typedef vector<vl> vvl;
typedef vector<double> vd;
typedef vector<vd> vvd;
typedef vector<string> vs;

const int INF = 1e9;
const int MOD = 1e9 + 7;
const double EPS = 1e-9;

template <typename T1, typename T2>
ostream &operator<<(ostream &os, const pair<T1, T2> &p) {
  return os << '(' << p.first << ',' << p.second << ')';
}
template <typename T> ostream &operator<<(ostream &os, const vector<T> &a) {
  os << '[';
  rep(i, a.size()) os << (i ? " " : "") << a[i];
  return os << ']';
}

typedef vector<vvi> vvvi;
typedef vector<vvvi> vvvvi;

template <typename Functor> struct functor_traits {
  template <typename C, typename Ret, typename Arg, typename... Args>
  static Arg helper(Ret (C::*)(Arg, Args...));
  template <typename C, typename Ret, typename Arg, typename... Args>
  static Arg helper(Ret (C::*)(Arg, Args...) const);
  typedef decltype(helper(&Functor::operator())) first_argument_type;
};
template <typename Compare,
          typename T = typename functor_traits<Compare>::first_argument_type>
priority_queue<T, vector<T>, Compare> make_priority_queue(Compare comp) {
  return priority_queue<T, vector<T>, Compare>(move(comp));
}

bool in(int h, int w, int i, int j) {
  return 0 <= i && i < h && 0 <= j && j < w;
}
bool in(int h, int w, pii p) { return in(h, w, p.first, p.second); }

int calc(vs grid, pii king, pii a, pii b) {
  int h = grid.size(), w = grid[0].size();
  rep(i, 2) rep(j, 2) grid[king.first + i][king.second + j] = '*';
  vvi dist(h, vi(w, INF));
  queue<tuple<int, int, int>> q;
  q.emplace(a.first, a.second, 0);
  while (q.size()) {
    int i, j, d;
    tie(i, j, d) = q.front();
    q.pop();
    if (!in(h, w, i, j) || grid[i][j] == '*' || dist[i][j] != INF)
      continue;
    dist[i][j] = d;
    if (mp(i, j) == b)
      return d;
    rep(k, 4) q.emplace(i + "\xff\x1\0\0"[k], j + "\0\0\xff\x1"[k], d + 1);
  }
  return dist[b.first][b.second];
}

int calc(vs grid, pii king, pii p1, pii p2, pii q1, pii q2) {
  return min(calc(grid, king, p1, q1) + calc(grid, king, p2, q2),
             calc(grid, king, p1, q2) + calc(grid, king, p2, q1));
  // int h=grid.size(),w=grid[0].size();
  // rep(i,2) rep(j,2) grid[king.first+i][king.second+j]='*';
  // vvvvi dist(h,vvvi(w,vvi(h,vi(w,INF))));
  // queue<tuple<int,int,int,int,int>> q;
  // q.emplace(p1.first,p1.second,p2.first,p2.second,0);
  // while(q.size()){
  //	int i1,j1,i2,j2,d; tie(i1,j1,i2,j2,d)=q.front(); q.pop();
  //	if(!in(h,w,i1,j1) || !in(h,w,i2,j2) || grid[i1][j1]=='*' ||
  //grid[i2][j2]=='*'
  //	|| (i1==i2 && j1==j2) || dist[i1][j1][i2][j2]!=INF) continue;
  //	dist[i1][j1][i2][j2]=dist[i2][j2][i1][j1]=d;
  //	rep(k,4){
  //		q.emplace(i1+"\xff\x1\0\0"[k],j1+"\0\0\xff\x1"[k],i2,j2,d+1);
  //		q.emplace(i1,j1,i2+"\xff\x1\0\0"[k],j2+"\0\0\xff\x1"[k],d+1);
  //	}
  // }
  // return dist[q1.first][q1.second][q2.first][q2.second];
}

int main() {
  for (int h, w; cin >> h >> w && h | w;) {
    vs grid(h);
    rep(i, h) cin >> grid[i];
    // dump(mp(h,w));
    // rep(i,h) cout<<grid[i]<<endl;

    if (grid[0][0] == 'X') {
      cout << 0 << endl;
      continue;
    }

    auto pq = make_priority_queue(
        [](tuple<int, int, int, int> a, tuple<int, int, int, int> b) {
          return get<3>(a) > get<3>(b);
        });
    {
      pii king(-1, -1), open1(-1, -1), open2(-1, -1);
      rep(i, h) rep(j, w) {
        if (grid[i][j] == 'X') {
          if (king == mp(-1, -1))
            king = mp(i, j);
          grid[i][j] = '.';
        } else if (grid[i][j] == '.')
          (open1 == mp(-1, -1) ? open1 : open2) = mp(i, j);
        else if (grid[i][j] == 'o')
          grid[i][j] = '.';
      }
      int ki = king.first, kj = king.second;
      if (in(h, w, ki - 1, kj) && grid[ki - 1][kj] != '*' &&
          grid[ki - 1][kj + 1] != '*')
        pq.emplace(
            ki, kj, 0,
            calc(grid, king, open1, open2, mp(ki - 1, kj), mp(ki - 1, kj + 1)));
      if (in(h, w, ki + 2, kj) && grid[ki + 2][kj] != '*' &&
          grid[ki + 2][kj + 1] != '*')
        pq.emplace(
            ki, kj, 1,
            calc(grid, king, open1, open2, mp(ki + 2, kj), mp(ki + 2, kj + 1)));
      if (in(h, w, ki, kj - 1) && grid[ki][kj - 1] != '*' &&
          grid[ki + 1][kj - 1] != '*')
        pq.emplace(
            ki, kj, 2,
            calc(grid, king, open1, open2, mp(ki, kj - 1), mp(ki + 1, kj - 1)));
      if (in(h, w, ki, kj + 2) && grid[ki][kj + 2] != '*' &&
          grid[ki + 1][kj + 2] != '*')
        pq.emplace(
            ki, kj, 3,
            calc(grid, king, open1, open2, mp(ki, kj + 2), mp(ki + 1, kj + 2)));
    }

    vvvi dist(h, vvi(w, vi(4, INF)));
    while (pq.size()) {
      // if(rand()%1000==0) printf("> %d\n",pq.size());
      int ki, kj, dir, step;
      tie(ki, kj, dir, step) = pq.top();
      pq.pop();
      if (!in(h, w, ki, kj) || dist[ki][kj][dir] != INF)
        continue;
      dist[ki][kj][dir] = step;
      if (step >= INF)
        break;

      pii open1, open2;
      if (dir == 0)
        open1 = mp(ki - 1, kj), open2 = mp(ki - 1, kj + 1);
      if (dir == 1)
        open1 = mp(ki + 2, kj), open2 = mp(ki + 2, kj + 1);
      if (dir == 2)
        open1 = mp(ki, kj - 1), open2 = mp(ki + 1, kj - 1);
      if (dir == 3)
        open1 = mp(ki, kj + 2), open2 = mp(ki + 1, kj + 2);

      pq.emplace(ki + "\xff\x1\0\0"[dir], kj + "\0\0\xff\x1"[dir], dir ^ 1,
                 step + 1);
      if (in(h, w, ki - 1, kj) && grid[ki - 1][kj] != '*' &&
          grid[ki - 1][kj + 1] != '*')
        pq.emplace(ki, kj, 0,
                   step + calc(grid, mp(ki, kj), open1, open2, mp(ki - 1, kj),
                               mp(ki - 1, kj + 1)));
      if (in(h, w, ki + 2, kj) && grid[ki + 2][kj] != '*' &&
          grid[ki + 2][kj + 1] != '*')
        pq.emplace(ki, kj, 1,
                   step + calc(grid, mp(ki, kj), open1, open2, mp(ki + 2, kj),
                               mp(ki + 2, kj + 1)));
      if (in(h, w, ki, kj - 1) && grid[ki][kj - 1] != '*' &&
          grid[ki + 1][kj - 1] != '*')
        pq.emplace(ki, kj, 2,
                   step + calc(grid, mp(ki, kj), open1, open2, mp(ki, kj - 1),
                               mp(ki + 1, kj - 1)));
      if (in(h, w, ki, kj + 2) && grid[ki][kj + 2] != '*' &&
          grid[ki + 1][kj + 2] != '*')
        pq.emplace(ki, kj, 3,
                   step + calc(grid, mp(ki, kj), open1, open2, mp(ki, kj + 2),
                               mp(ki + 1, kj + 2)));
    }
    int res = *min_element(all(dist[0][0]));
    cout << (res < INF ? res : -1) << endl;
  }
}