//POJ-1077
#include <iostream>
#include <algorithm>
using namespace std;
const int M = 362880;
struct node
{
int state;//当前点表示方式
char action;//到达当前点的动作
int table;//0表示未访问,1表示在open表,2表示在close表,用于hash判重
int h;//h表示当前点到目标点的估计代价
int g;//g()表示原点到当前点的代价
int f;//f() = g() + h()
}hash[M];
int rnums[10], total;
int nums[10];
int fac[10] = {0, 1, 1, 2, 6, 24, 120, 720, 5040, 40320};
char actions[10][6] = //每个位置对应的后续状态为有限个
{
{' '},
{'r', 'd'},
{'l', 'r', 'd'},
{'l', 'd'},
{'u', 'r', 'd'},
{'u', 'l', 'r', 'd'},
{'u', 'l', 'd'},
{'u', 'r'},
{'u', 'l', 'r'},
{'u', 'l'}
};
int manhattan[10][10] = //第i个数及其所处不同位置的Manhattan路径长度
{
{-1,-1,-1,-1,-1,-1,-1,-1,-1,-1},
{-1, 0, 1, 2, 1, 2, 3, 2, 3, 4},
{-1, 1, 0, 1, 2, 1, 2, 3, 2, 3},
{-1, 2, 1, 0, 3, 2, 1, 4, 3, 2},
{-1, 1, 2, 3, 0, 1, 2, 1, 2, 3},
{-1, 2, 1, 2, 1, 0, 1, 2, 1, 2},
{-1, 3, 2, 1, 2, 1, 0, 3, 2, 1},
{-1, 2, 3, 4, 1, 2, 3, 0, 1, 2},
{-1, 3, 2, 3, 2, 1, 2, 1, 0, 1},
{-1, 4, 3, 2, 3, 2, 1, 2, 1, 0}
};
int init_state = 0, end_state = 123456789;
int heap[M], top = 0;//保存的值为hash的key值,key值是由state的 reverseNum * fac 计算的
void BUheapify(int k)
{
while(k > 1 && hash[heap[k/2]].f > hash[heap[k]].f)
{
swap(heap[k],heap[k/2]);
k /= 2;
}
}
void TDheapify(int k, int N)
{
int i;
while(2 * k < N)
{
i = 2 * k;
if(hash[heap[i]].f > hash[heap[i+1]].f)
i++;
if(!(hash[heap[k]].f > hash[heap[i]].f))
break;
swap(heap[k],heap[i]);
k = i;
}
}
void PQinit() {top = 0;}
int PQempty() {return top == 0;}
void PQinsert(int key)
{
heap[++top] = key;
BUheapify(top);
}
int PQdelmin()
{
swap(heap[1],heap[top]);
TDheapify(1, top-1);
return heap[top--];
}
int exp(int k)
{
int res = 1;
while(k--) res *= 10;
return res;
}
int moveR(int state) { return state + 1;}
int moveL(int state) { return state - 1;}
int moveU(int state)
{
int n, x, y;
n = 9 - state % 10 + 1;
x = state % exp(n);
y = state / exp(n);
y = y/1000*1000 + y%1000/100 + y%1000%100*10;
return x - 3 + y*exp(n);
}
int moveD(int state)
{
int n, x, y;
n = 9 - state % 10 + 1;
x = state % exp(n);
y = state / exp(n);
x = x % exp(n-3) + (x / exp(n-3) % 10 *100 + x /exp(n-3) /10) * exp(n-3);
return x + y*exp(n)+3;
}
int getNum(int state, int p)
{
return state/exp(9-p)%10;
}
int getRevNum(int state)
{
int total = 0;
for(int i = 1; i <= 8; ++i)
rnums[i] = 0;
for(int i = 1; i <=8 ; ++i)
{
int num = getNum(state, i);
nums[i] = num;
for(int j = i-1; j >= 1; --j)
{
if(nums[j] > num)
{
++rnums[i];
++total;
}
}
}
return total;
}
int getHashNum(int state)
{
getRevNum(state);
int key = 0;
for(int i = 1; i <= 8; ++i)
key += rnums[i] * fac[i];
key += (9 - getNum(state,9)) * fac[9];
return key;
}
int getManhattan(int state)//用作估价函数的h值
{
int total = 0,k;
for(int i = 1; i <= 8; ++i)
{
k = getNum(state, i);
total += manhattan[k][i];
}
return total;
}
void output(int state)
{
int key = getHashNum(state);
char action = hash[key].action;
if(action != 's')
{
if(action == 'l') {output(moveR(state)); cout << "l";}
if(action == 'r') {output(moveL(state)); cout << "r";}
if(action == 'u') {output(moveD(state)); cout << "u";}
if(action == 'd') {output(moveU(state)); cout << "d";}
}
}
void Best_First_Search()
{
int x, state1, key1, state2, key2;
char action;
key1 = getHashNum(init_state);
hash[key1].state = init_state;
hash[key1].action = 's';
hash[key1].table = 1;
hash[key1].g = 0;
PQinit();
PQinsert(key1);
while(!PQempty())
{
key1 = PQdelmin();
hash[key1].table = 2;
if(hash[key1].state == end_state)
{
output(hash[key1].state);
break;
}
x = hash[key1].state % 10;
state1 = hash[key1].state;
for(int i = 0; i <= 4; ++i)
{
action = actions[x][i];
if(action != 'l' && action != 'r' && action != 'u' &&action != 'd')
continue;
if(action == 'l') {state2 = moveL(state1); key2 = getHashNum(state2);}
if(action == 'r') {state2 = moveR(state1); key2 = getHashNum(state2);}
if(action == 'u') {state2 = moveU(state1); key2 = getHashNum(state2);}
if(action == 'd') {state2 = moveD(state1); key2 = getHashNum(state2);}
if(hash[key2].table == 1)
{
if(hash[key1].g + 1 < hash[key2].g)
{
hash[key2].g = hash[key1].g + 1;
hash[key2].f = hash[key2].g + hash[key2].h;
for(int j = top; j >= 2 ; --j)
BUheapify(j);
}
}
else if(hash[key2].table == 0)
{
hash[key2].state = state2;
hash[key2].action = action;
hash[key2].table = 1;
hash[key2].g = hash[key1].g + 1;
hash[key2].h = getManhattan(state2)*9;
hash[key2].f = hash[key2].g + hash[key2].h;
PQinsert(key2);
}
else if(hash[key2].table == 2)
continue;
}
}
}
int main()
{
char num, trash;
int blank;
for(int i = 1; i <= 9; ++i)
{
cin.get(num);
cin.get(trash);
if(num != 'x')
init_state = init_state * 10 + int(num - '0');
else
blank = i;
}
//2 3 4 1 5 x 7 6 8
init_state = init_state * 10 + blank;
Best_First_Search();
return 0;
}