Problem:
Problem C: Cubic Eight-Puzzle

Let's play a puzzle using eight cubes placed on a 3 × 3 board leaving one empty square.

Faces of cubes are painted with three colors. As a puzzle step, you can roll one of the cubes to
the adjacent empty square. Your goal is to make the specified color pattern visible from above
by a number of such steps.

The rules of this puzzle are as follows.

Coloring of Cubes: All the cubes are colored in the same way as shown in Figure 3.
The opposite faces have the same color.

Figure 3: Coloring of a cube

Initial Board State: Eight cubes are placed on the 3 × 3 board leaving one empty square.
All the cubes have the same orientation as shown in Figure 4. As shown in the figure,
squares on the board are given x and y coordinates, (1, 1), (1, 2), .. ., and (3, 3). The
position of the initially empty square may vary.

Figure 4: Initial board state

Rolling Cubes: At each step, we can choose one of the cubes adjacent to the empty square and roll it into the empty square, leaving the original position empty. Figure 5
shows an example.

Figure 5: Rolling a cube

Goal: The goal of this puzzle is to arrange the cubes so that their top faces form the
specified color pattern by a number of cube rolling steps described above.

Your task is to write a program that finds the minimum number of steps required to make the
specified color pattern from the given initial state.

Input

The input is a sequence of datasets. The end of the input is indicated by a line containing two
zeros separated by a space. The number of datasets is less than 16. Each dataset is formatted
as follows.

x y
F11 F21 F31
F12 F22 F32
F13 F23 F33

The first line contains two integers x and y separated by a space, indicating the position (x, y)
of the initially empty square. The values of x and y are 1, 2, or 3.

The following three lines specify the color pattern to make. Each line contains three characters
F1j, F2j, and F3j, separated by a space. Character Fij indicates the top color of the cube, if any, at position (i, j) as follows:

B: Blue
W: White
R: Red
E: the square is Empty.

There is exactly one 'E' character in each dataset.

Output

For each dataset, output the minimum number of steps to achieve the goal, when the goal can
be reached within 30 steps. Otherwise, output "-1" for the dataset.

Sample Input

1 2
W W W
E W W
W W W
2 1
R B W
R W W
E W W
3 3
W B W
B R E
R B R
3 3
B W R
B W R
B E R
2 1
B B B
B R B
B R E
1 1
R R R
W W W
R R E
2 1
R R R
B W B
R R E
3 2
R R R
W E W
R R R
0 0

Output for the Sample Input

0
3
13
23
29
30
-1
-1

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

#include <iostream>
#include <cstdio>
#include <vector>
#include <list>
#include <cmath>
#include <fstream>
#include <algorithm>
#include <string>
#include <queue>
#include <set>
#include <map>
#include <complex>
#include <iterator>
#include <cstdlib>
#include <cstring>
#include <sstream>
#include <stack>
#include <climits>
#include <deque>
#include <bitset>
#include <cassert>
#include <ctime>
using namespace std;

typedef long long ll;
typedef pair<int,int> pii;
const int dy[]={-1,0,1,0},dx[]={0,1,0,-1};
// adjust problem by problem
const double EPS=1e-8;
const double PI=acos(-1.0);
#ifdef __GNUC__
int popcount(int n){return __builtin_popcount(n);}
int popcount(ll n){return __builtin_popcountll(n);}
#endif
#ifndef __GNUC__
template<class T> int popcount(T n){int cnt=0;while(n){if(n%2)cnt++;n/=2;}return cnt;}
#endif
template<class T>int SIZE(T a){return a.size();}
template<class T>string IntToString(T num){string res;stringstream ss;ss<<num;return ss.str();}
template<class T>T StringToInt(string str){T res=0;for(int i=0;i<SIZE(str);i++)res=(res*10+str[i]-'0');return res;}
template<class T>T gcd(T a,T b){if(b==0)return a;return gcd(b,a%b);}
template<class T>T lcm(T a,T b){return a/gcd(a,b)*b;}
bool EQ(double a,double b){return abs(a-b)<EPS;}
void fastStream(){cin.tie(0);std::ios_base::sync_with_stdio(0);}
vector<string> split(string str,char del){
  vector<string> res;
  for(int i=0,s=0;i<SIZE(str);i++){
    if(str[i]==del){if(i-s!=0)res.push_back(str.substr(s,i-s));s=i+1;}
    else if(i==SIZE(str)-1){res.push_back(str.substr(s));}
  }
  return res;
}

typedef vector<pii> vec;
typedef vector<vec> mat;

int sy,sx;
int goal[3][3];
// 0->red,1->blue,2->white
mat field(3,vec(3));
const int INF=1<<30;
set<mat> used;
int ary[3][3];

int dcdColor(int a,int b){
  if(a==0&&b==1)return 2;
  else if(a==0&&b==2)return 1;
  else if(a==1&&b==0)return 2;
  else if(a==1&&b==2)return 0;
  else if(a==2&&b==0)return 1;
  else if(a==2&&b==1)return 0;
}

// iddfsでgoalに到達できるかどうかを探索
// 辿りつけなければ-1を返す
int iddfs(int depth,int limDepth,int cy,int cx){
  // 距離を計算
  int cnt=0;
  for(int j=0;j<3;j++)
    for(int k=0;k<3;k++)
      cnt+=(field[j][k].first!=goal[j][k]);
  if(depth==limDepth){
    if(cnt==0)return depth;
    return -1;
  }
  // 異なる面の数がのこりの移動回数+1以下ならok
  if(cnt>(limDepth-depth)+1)return -1;
  for(int i=0;i<4;i++){
    int ny=cy+dy[i];
    int nx=cx+dx[i];
    // enable to move
    if(ny>=0&&nx>=0&&ny<3&&nx<3){
      pii p1=field[cy][cx];
      pii p2=field[ny][nx];
      // 移動先の要素を回転させて今の場所へ持ってくる
      if(nx!=cx){
        field[cy][cx].first=ary[field[ny][nx].first][field[ny][nx].second];
        field[cy][cx].second=field[ny][nx].second;
      }
      else if(ny!=cy){
        field[cy][cx]=field[ny][nx];
        swap(field[cy][cx].first,field[cy][cx].second);
      }
      field[ny][nx].first=field[ny][nx].second=-1;
      if(used.count(field)==0){
        used.insert(field);
        int res=iddfs(depth+1,limDepth,ny,nx);
        if(res!=-1)return res;
        used.erase(field);
      }
      // back track
      field[cy][cx]=p1;
      field[ny][nx]=p2;
    }
  }
  return -1;
}

int main(){
  for(int i=0;i<3;i++)
    for(int j=0;j<3;j++)
      ary[i][j]=dcdColor(i,j);
  while(cin>>sx>>sy&&(sx|sy)){
    // topfaceがgoalとmatchしたら終了
    for(int i=0;i<3;i++){
      for(int j=0;j<3;j++){
        char ch;
        cin>>ch;
        if(ch=='R')goal[i][j]=0;
        else if(ch=='B')goal[i][j]=1;
        else if(ch=='W')goal[i][j]=2;
        else goal[i][j]=-1;
      }
    }
    sy--,sx--;
    // start地点をセット
    for(int i=0;i<3;i++){
      for(int j=0;j<3;j++){
        if(i==sy&&j==sx)field[i][j]=pii(-1,-1);
        else field[i][j]=pii(2,0);
      }
    }
    int res=-1;
    for(int d=0;d<=30;d++){
      //cout<<d<<" "<<flush;
      used.clear();
      // start地点をセット
      for(int i=0;i<3;i++){
        for(int j=0;j<3;j++){
          if(i==sy&&j==sx)field[i][j]=pii(-1,-1);
          else field[i][j]=pii(2,0);
        }
      }
      used.insert(field);
      res=iddfs(0,d,sy,sx);
      if(res!=-1){
        res=d;
        break;
      }
    }
    //cout<<endl;
    //cout<<res<<endl<<flush;
    cout<<res<<endl;
  }
  return 0;
}