Problem:
Problem E: Sliding Block Puzzle

In sliding block puzzles, we repeatedly slide pieces (blocks) to open spaces within a frame to establish a goal placement of pieces.

A puzzle creator has designed a new puzzle by combining the ideas of sliding block puzzles and mazes. The puzzle is played in a rectangular frame segmented into unit squares. Some squares are pre-occupied by obstacles. There are a number of pieces placed in the frame, one 2 × 2 king piece and some number of 1 × 1 pawn pieces. Exactly two 1 × 1 squares are left open. If a pawn piece is adjacent to an open square, we can slide the piece there. If a whole edge of the king piece is adjacent to two open squares, we can slide the king piece. We cannot move the obstacles. Starting from a given initial placement, the objective of the puzzle is to move the king piece to the upper-left corner of the frame.

The following figure illustrates the initial placement of the fourth dataset of the sample input.

Figure E.1: The fourth dataset of the sample input.

Your task is to write a program that computes the minimum number of moves to solve the puzzle from a given placement of pieces. Here, one move means sliding either king or pawn piece to an adjacent position.

Input

The input is a sequence of datasets. The first line of a dataset consists of two integers H and W separated by a space, where H and W are the height and the width of the frame. The following H lines, each consisting of W characters, denote the initial placement of pieces. In those H lines, 'X', 'o', '*', and '.' denote a part of the king piece, a pawn piece, an obstacle, and an open square, respectively. There are no other characters in those H lines. You may assume that 3 ≤ H ≤ 50 and 3 ≤ W ≤ 50.

A line containing two zeros separated by a space indicates the end of the input.

Output

For each dataset, output a line containing the minimum number of moves required to move the king piece to the upper-left corner. If there is no way to do so, output -1.

Sample Input

3 3
oo.
oXX
.XX
3 3
XXo
XX.
o.o
3 5
.o*XX
oooXX
oooo.
7 12
oooooooooooo
ooooo*****oo
oooooo****oo
o**ooo***ooo
o***ooooo..o
o**ooooooXXo
ooooo****XXo
5 30
oooooooooooooooooooooooooooooo
oooooooooooooooooooooooooooooo
o***************************oo
XX.ooooooooooooooooooooooooooo
XX.ooooooooooooooooooooooooooo
0 0

Output for the Sample Input

11
0
-1
382
6807

Solution in C++ (judge verdict: Accepted)

#include <iostream>
#include <sstream>
#include <cstdio>
#include <cstdlib>
#include <cmath>
#include <ctime>
#include <cstring>
#include <string>
#include <vector>
#include <stack>
#include <queue>
#include <deque>
#include <map>
#include <set>
#include <bitset>
#include <numeric>
#include <utility>
#include <iomanip>
#include <algorithm>
#include <functional>
using namespace std;

typedef long long ll;
typedef vector<int> vint;
typedef vector<long long> vll;
typedef pair<int,int> pint;
typedef pair<long long, long long> pll;

#define MP make_pair
#define PB push_back
#define ALL(s) (s).begin(),(s).end()
#define EACH(i, s) for (__typeof__((s).begin()) i = (s).begin(); i != (s).end(); ++i)
#define COUT(x) cout << #x << " = " << (x) << " (L" << __LINE__ << ")" << endl

template<class T> inline bool chmax(T& a, T b) { if (a < b) { a = b; return 1; } return 0; }
template<class T> inline bool chmin(T& a, T b) { if (a > b) { a = b; return 1; } return 0; }
template<class T1, class T2> ostream& operator << (ostream &s, pair<T1,T2> P) 
{ return s << '<' << P.first << ", " << P.second << '>'; }
template<class T> ostream& operator << (ostream &s, vector<T> P) 
{ for (int i = 0; i < P.size(); ++i) { if (i > 0) { s << " "; } s << P[i]; } return s; }
template<class T> ostream& operator << (ostream &s, vector<vector<T> > P) 
{ for (int i = 0; i < P.size(); ++i) { s << endl << P[i]; } return s << endl; }
template<class T1, class T2> ostream& operator << (ostream &s, map<T1,T2> P) 
{ EACH(it, P) { s << "<" << it->first << "->" << it->second << "> "; } return s; }

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

int n, m;
string fi[55];
int dist[55][55][55][55];
int dp[55][55][6];

inline int len(pint s1, pint s2, pint t1, pint t2) {
    int res = INF;
    chmin(res, dist[s1.first][s1.second][t1.first][t1.second] + dist[s2.first][s2.second][t2.first][t2.second]);
    chmin(res, dist[s1.first][s1.second][t2.first][t2.second] + dist[s2.first][s2.second][t1.first][t1.second]);
    return res;
}

int main() {
    //freopen( "/Users/macuser/Dropbox/Contest/input.in", "r", stdin );
    
    while (cin >> n >> m) {
        if (n == 0) break;
        for (int i = 0; i < n; ++i) cin >> fi[i];
        
        int ikx = -1, iky = -1, iex[2] = {-1}, iey[2] = {-1};
        for (int i = 0; i < n; ++i) for (int j = 0; j < m; ++j) {
            if (fi[i][j] == 'X') {
                if (ikx != -1) continue;
                ikx = i, iky = j;
            }
            if (fi[i][j] == '.') {
                if (iex[0] != -1) iex[1] = i, iey[1] = j;
                else iex[0] = i, iey[0] = j;
            }
        }
        //cout << pint(iex[0],iey[0]) << ", " << pint(iex[1],iey[1]) << endl;
        
        int res = INF;
        for (int i = 0; i < 55; ++i) for (int j = 0; j < 55; ++j) for (int k = 0; k < 6; ++k) dp[i][j][k] = INF;
        dp[ikx][iky][4] = 0;
        priority_queue< pair<int,pair<pint,int> >, vector<pair<int,pair<pint,int> > >, greater<pair<int,pair<pint,int> > > > que;
        que.push( MP(0, MP(pint(ikx,iky),4)) );
        while (!que.empty()) {
            int dis = que.top().first;
            int kx = que.top().second.first.first;
            int ky = que.top().second.first.second;
            int dir = que.top().second.second;
            que.pop();
            
            if (kx == 0 && ky == 0) {
                chmin(res, dis);
                break;
            }
            if (dis > dp[kx][ky][dir]) continue;
            
            //cout << pint(kx,ky) << ", " << dir << " : " << dis << endl;
            
            int pex[2], pey[2], nex[2], ney[2];
            if (dir == 4) pex[0] = iex[0], pey[0] = iey[0], pex[1] = iex[1], pey[1] = iey[1];
            if (dir == 0) pex[0] = kx-1, pey[0] = ky, pex[1] = kx-1, pey[1] = ky+1;
            if (dir == 1) pex[0] = kx, pey[0] = ky-1, pex[1] = kx+1, pey[1] = ky-1;
            if (dir == 2) pex[0] = kx+2, pey[0] = ky, pex[1] = kx+2, pey[1] = ky+1;
            if (dir == 3) pex[0] = kx, pey[0] = ky+2, pex[1] = kx+1, pey[1] = ky+2;
            
            for (int it = 0; it < 2; ++it) {
                int ix = pex[it], iy = pey[it];
                for (int i = 0; i < n; ++i) for (int j = 0; j < m; ++j) dist[ix][iy][i][j] = INF;
                dist[ix][iy][ix][iy] = 0;
               
                //if (fi[i][j] == '*') continue;
                //dist[i][j][i][j] = 0;
                queue<pint> que;
                que.push(pint(ix, iy));
                while (!que.empty()) {
                    int x = que.front().first, y = que.front().second; que.pop();
                    for (int k = 0; k < 4; ++k) {
                        int nx = x + dx[k], ny = y + dy[k];
                        if (nx < 0 || nx >= n || ny < 0 || ny >= m) continue;
                        if (fi[nx][ny] == '*') continue;
                        if (nx == kx && ny == ky) continue;
                        if (nx == kx+1 && ny == ky) continue;
                        if (nx == kx && ny == ky+1) continue;
                        if (nx == kx+1 && ny == ky+1) continue;
                        if (dist[ix][iy][nx][ny] == INF) {
                            dist[ix][iy][nx][ny] = dist[ix][iy][x][y] + 1;
                            que.push(pint(nx, ny));
                        }
                    }
                }
            }
            
            for (int i = 0; i < 4; ++i) {
                int nkx = kx + dx[i], nky = ky + dy[i];
                if (nkx < 0 || nkx >= n-1 || nky < 0 || nky >= m-1) continue;
                if (i == 2) nex[0] = kx-1, ney[0] = ky, nex[1] = kx-1, ney[1] = ky+1;
                if (i == 3) nex[0] = kx, ney[0] = ky-1, nex[1] = kx+1, ney[1] = ky-1;
                if (i == 0) nex[0] = kx+2, ney[0] = ky, nex[1] = kx+2, ney[1] = ky+1;
                if (i == 1) nex[0] = kx, ney[0] = ky+2, nex[1] = kx+1, ney[1] = ky+2;
                
                if (fi[nex[0]][ney[0]] == '*' || fi[nex[1]][ney[1]] == '*') continue;
                int l = len(pint(pex[0],pey[0]), pint(pex[1],pey[1]), pint(nex[0],ney[0]), pint(nex[1],ney[1])) + 1;
                
                if (l >= INF) continue;
                if (chmin(dp[nkx][nky][i], dp[kx][ky][dir] + l)) {
                    que.push( MP(dp[kx][ky][dir]+l, MP(pint(nkx,nky), i)) );
                }
            }
        }
        
        if (res < INF) cout << res << endl;
        else cout << -1 << endl;
    }
    return 0;
}