Problem:
氷の迷路

四角のマスを縦横にならべた長方形の迷路があります。この迷路では東西南北の隣接するマスへ移動しながら、スタートのマスSを出発し、ゴールのマスGを目指します。マスの種類には、平原、山、氷の３種類があります。SとGは、平原のマスに置かれています。平原のマスには移動できますが、山のマスには移動できません。氷のマスは移動できますが、条件によって氷が割れ動けなくなります。

氷のマスは東西南北に隣接するもの全体でひとつの塊として扱われます。

氷の塊のなかで、マスの個数の半分より多くのマスに移動すると、塊全体が割れます。

例えば、図１は与えられた迷路の最短経路のステップ数が 11 であることを示しています。

図1

しかし、図２のように氷のマスを通って近道をしようとすると、大きさが６の氷の塊に対する４回目の移動後に動けなくなってしまいGには到達できません。

図2

このような迷路の情報を入力とし、SからGまでの最短経路のステップ数を求めるプログラムを作成してください。マスの種類はそれぞれ以下の文字で表されます：

文字（半角）

マスの種類

. （ピリオド）

平原

#（シャープ）

山

X

氷

与えられる迷路は必ず解けるものとします。迷路はその東西方向のマスの数 X、南北方向のマスの数 Y と X × Y 個の文字として与えられます。

入力

複数のデータセットが与えられます。入力の終わりはゼロふたつの行で示されます。各データセットは以下の形式で与えられます。

X Y
line1
line2
:
lineY

1行目に迷路の大きさを表す整数 X, Y (2 ≤ X, Y ≤ 12) が与えられます。続く Y 行に迷路の i 行目の情報 linei (長さ X の半角英文字列) が与えられます。

データセットの数は 40 を超えない。

出力

データセットごとに、最小のステップ数を１行に出力します。

入力例

5 5
.X.S.
.X#..
.XX##
.#XG.
..X..
7 3
SXX.XXG
X.#.#X.
XXX.XX#
4 4
S...
X.X.
GX..
...X
10 10
..XXXXX.XX
.X.#.#X.XX
SX.#X.X..X
#X.##.X.XX
..XXXX#.XX
##.##.##XX
....X.XX#X
.##X..#X#X
....XX#..X
...#XXG..X
0 0

出力例

11
10
10
33

Solution in C++11 (judge verdict: Time Limit Exceeded)

#include <bits/stdc++.h>

using namespace std;

#define LOG(...) fprintf(stderr,__VA_ARGS__)
//#define LOG(...)
#define FOR(i,a,b) for(int i=(int)(a);i<(int)(b);++i)
#define REP(i,n) for(int i=0;i<(int)(n);++i)
#define ALL(a) (a).begin(),(a).end()
#define RALL(a) (a).rbegin(),(a).rend()
#define EXIST(s,e) ((s).find(e)!=(s).end())
#define SORT(c) sort(ALL(c))
#define RSORT(c) sort(RALL(c))

typedef long long ll;
typedef unsigned long long ull;
typedef vector<bool> vb;
typedef vector<int> vi;
typedef vector<ll> vll;
typedef vector<vb> vvb;
typedef vector<vi> vvi;
typedef vector<vll> vvll;
typedef pair<int,int> pii;
typedef pair<ll,ll> pll;

#define INF 1e9

int W, H;
int start_x, start_y, goal_x, goal_y;
int *ices[12][12];
char maze[12][12];
bool G[12][12];
int depth;

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

void dfs_count(int *ice, int x, int y) {
    (*ice)++;
    ices[y][x] = ice;
    maze[y][x] = '?'; // used

    REP(i, 4) {
        int sx = x + dx[i], sy = y + dy[i];
        if (0 <= sx && sx < W && 0 <= sy && sy < H) {
            if (maze[sy][sx] == 'X') {
                dfs_count(ice, sx, sy);
            }
        }
    }
}

bool iddfs(int x, int y, int step) {
    if (x == goal_x && y == goal_y) return true;
    if (step == depth) return false;
    REP(i, 4) {
        int sx = x + dx[i], sy = y + dy[i];
        if (0 <= sx && sx < W && 0 <= sy && sy < H) {
            if (*ices[sy][sx] > 0) {
                (*ices[sy][sx])--;
                if (iddfs(sx, sy, step+1)) return true;
                (*ices[sy][sx])++;
            }
        }
    }
    return false;
}

int main() {
    while (cin >> W >> H, W|H) {
        REP(y, H) REP(x, W) cin >> maze[y][x];

        int ice[12][12] = {};

        REP(y, H) REP(x, W) {
            switch (maze[y][x]) {
            case '.':
                ice[y][x] = 1;
                ices[y][x] = &ice[y][x];
                break;
            case '#':
                ices[y][x] = &ice[y][x];
                break;
            case 'S':
                start_x = x;
                start_y = y;
                ice[y][x] = 1;
                ices[y][x] = &ice[y][x];
                break;
            case 'G':
                goal_x = x;
                goal_y = y;
                ice[y][x] = 1;
                ices[y][x] = &ice[y][x];
                break;
            case 'X': {
                dfs_count(&ice[y][x], x, y);
                ice[y][x] /= 2;
                ices[y][x] = &ice[y][x];
                break;
            }
            }
            maze[y][x] = '?'; // used
        }

        fill_n((bool *)G, 12*12, false);
        depth = abs(start_x - goal_x) + abs(start_y - goal_y);
        while (!iddfs(start_x, start_y, 0)) {
            depth++;
        }
        cout << depth << endl;
    }
}