Language: C++

#include<iostream>
#include<map>
#include<vector>
#include<cstdio>
#include<algorithm>
#include<sstream>
#include<queue>
#include<cassert>
#include<deque>
#include<set>

#define REP(i,s,n) for(int i=s;i<n;i++)
#define rep(i,n) REP(i,0,n)
#define inf (1<<29)
#define all(n) (n).begin(),(n).end()
#define MAX 12
#define sinf (30000)
#define cinf (254)

using namespace std;

typedef unsigned short us;
typedef unsigned char uc;

struct Pox
{
  vector<uc> array;
  us cost;
  us prev;
  Pox(vector<uc> array=vector<uc>(),us cost=cinf,us prev=cinf):array(array),cost(cost),prev(prev){}
};

uc dx[] = {1,0,-1,0};
uc dy[] = {0,-1,0,1};
uc max_ans;
uc ev[MAX*MAX][MAX*MAX];//評価値 ev[a][b] := aからbまでの最短コスト
char g[MAX][MAX];
us st[2],h,w,ice_number;
int ice[MAX*MAX];
uc ice_cnt[MAX*MAX];
set<vector<uc> > mincost;
deque<Pox> Q;



void init()
{
  max_ans = 0;
  ice_number = 0;
  rep(i,h)rep(j,w)
    {
      ice[j+i*w] = inf;
      ice_cnt[j+i*w] = cinf;
    }
}

void getInput()
{
  rep(i,h)
    {
      getchar();
      rep(j,w)
	{
	  scanf("%c",&g[i][j]);
	  if(g[i][j] == 'S')
	    {
	      st[0] = j + i * w;
	      g[i][j] = '.';
	    }
	  if(g[i][j] == 'G')
	    {
	      st[1] = j + i * w;
	      g[i][j] = '.';
	    }
	  if(g[i][j] == '.')max_ans++;
	}
    }
}

void make_ev()
{
  rep(sp,h*w)
    {
      ev[sp][sp] = 0;
      deque<us> deq;
      deq.push_back(sp);

      while(!deq.empty())
	{
	  uc cur = deq.front(); deq.pop_front();
	  if(cur == st[1])break;
	  rep(i,4)
	    {
	      uc nx = cur % w + dx[i];
	      uc ny = cur / w + dy[i];
	      if(!(0 <= nx && nx < w && 0 <= ny && ny < h))continue;
	      if(g[ny][nx] == '#')continue;
	      if(ev[sp][nx+ny*w] > ev[sp][cur]+1)
		{
		  ev[sp][nx+ny*w] = ev[sp][cur]+1;
		  deq.push_back(nx+ny*w);
		}
	    }
	}
    }
}

void draw(uc cur,uc id,int &cnt)
{
  if(ice[cur] != inf)return;
  ice[cur] = id;
  cnt++;
  rep(i,4)
    {
      uc nx = cur % w + dx[i];
      uc ny = cur / w + dy[i];
      if(!(0 <= nx && nx < w && 0 <= ny && ny < h))continue;
      if(g[ny][nx] != 'X')continue;
      draw(nx+ny*w,id,cnt);
    }
}

bool compute(us depth)
{
  while(!Q.empty())
    {
      Pox pox = Q.front(); Q.pop_front();
      
      if(st[1] == pox.array[ice_number])
	{
	  cout << pox.cost << endl;
	  return true;
	}

      if(pox.cost + ev[pox.array[ice_number]][st[1]] >= max_ans)
	{
	  continue;
	}
      
      if(pox.cost + ev[pox.array[ice_number]][st[1]] >= depth)
	{
	  Q.push_back(pox);
	  return false;
	}
      

      rep(i,4)
	{
	  if(pox.prev != -1 && pox.prev == (i+2)%4)continue;
	  uc nx = pox.array[ice_number] % w + dx[i];
	  uc ny = pox.array[ice_number] / w + dy[i];
	  if(!(0 <= nx && nx < w && 0 <= ny && ny < h))continue;
	  if(g[ny][nx] == '#')continue;

	  vector<uc> next = pox.array;	
	  next[ice_number] = nx+ny*w;  

	  if(g[ny][nx] == 'X')
	    {
	      if(ice_cnt[ice[nx+ny*w]] < 2*(pox.array[ice[nx+ny*w]] + 1))continue;

	      next[ice[nx+ny*w]]++;
	    }


	  if(mincost.find(next) == mincost.end())
	    {
	      mincost.insert(next);
	      if(Q.front().cost > pox.cost+1)
		Q.push_front(Pox(next,pox.cost+1,i));
	      else
		Q.push_back(Pox(next,pox.cost+1,i));
	    }
	}
    }
  return false;
}

int main()
{
  while(cin >> w >> h,w|h)
    {
      init();
      getInput();
      make_ev();

      rep(y,h)rep(x,w)
	if(g[y][x] == 'X' && ice[x+y*w] == inf)
	    {
	      int cnt = 0;
	      draw(x+y*w,ice_number,cnt);
	      ice_cnt[ice_number] = cnt;
	      ice_number++;      
	    }

      rep(i,ice_number)max_ans += ice_cnt[i]/2;

      vector<uc> initial_array(ice_number+1,0);
      initial_array[ice_number] = st[0];
      Q.push_back(Pox(initial_array,0,-1));
      mincost.insert(initial_array);
      us depth = 0;
      while(!compute(depth++))
	{
	  mincost.clear();
	}
      while(!Q.empty())Q.pop_back();
      mincost.clear();
    }
  return 0;
}

Compiler output:
a.cc:33:16: error: narrowing conversion of '-1' from 'int' to 'uc' {aka 'unsigned char'} [-Wnarrowing]
   33 | uc dx[] = {1,0,-1,0};
      |                ^~
a.cc:34:14: error: narrowing conversion of '-1' from 'int' to 'uc' {aka 'unsigned char'} [-Wnarrowing]
   34 | uc dy[] = {0,-1,0,1};
      |              ^~