//八数码问题的核心:把每个排列抽象成一个状态,计算从初始状态转移到最终状态的代价。
#include <bits/stdc++.h>
using namespace std;
const int LEN = 362880; //状态总数9!种
struct node
{
int stat[9];
int dis;
};
int dir[4][2] = {{-1 , 0} , {0 , -1} , {0 , 1} , {1 , 0}};
int vis[LEN]; //记录访问的状态数量
int start[9]; //开始状态
int goal[9] = {1 , 2 , 3, 4 , 5, 6, 7 , 8, 0}; //目标状态
long int fac[] = {1, 1, 2, 6 , 24 , 120 , 720 , 5040 , 40320 , 362880}; //Cantor()用到的常数
bool Cantor(int str[] , int n) //康托展开判重
{
long res = 0;
for(int i = 0; i < n; i ++)
{
int counted = 0;
for(int j = i + 1 ; j < n; j++)
{
if(str[i] > str[j])
{
++counted;
}
}
res += counted * fac[n - i - 1];
}
if(!vis[res])
{
vis[res] = 1;
return 1;
}else return 0;
}
int bfs()
{
node head;
memcpy(head.stat , start , sizeof(head.stat)); //初始化head为start
head.dis = 0;
queue<node> q;
q.push(head);
Cantor(head.stat , 9); //用Cantor()判重, 目的是对vis[LEN]赋初值
while(!q.empty())
{
head = q.front();
if(memcmp(head.stat , goal , sizeof(goal)) == 0) //说明找到了该目标
{
return head.dis;
}
q.pop();
//找到这个状态中元素0的位置
int z;
for(z = 0 ; z < 9 ; z ++)
{
if(head.stat[z] == 0) break;
}
//转化为z的横纵坐标
int x = z % 3;
int y = z / 3;
//扩散
for(int i = 0 ; i < 4 ; i++)
{
int newx = x + dir[i][0];
int newy = y + dir[i][1];
int nz = newx + 3 * newy;
if(newx >= 0 && newx < 3 && newy >= 0 && newy <3) //未越界
{
node newnode;
memcpy(&newnode , &head , sizeof(struct node)); //复制新的状态
swap(newnode.stat[z] ,newnode.stat[nz]); //把0移动到新的位置
newnode.dis ++;
if(Cantor(newnode.stat , 9))
{
q.push(newnode);
}
}
}
}
return -1 ; //没找到
}
int main()
{
for(int i = 0 ; i < 9 ; i++)
{
char c; cin >> c;
if(c != 'x') start[i] = c - '0';
else start[i] = 0;
}
int num = bfs();
if(num != -1 ) cout << num;
else cout << -1;
return 0;
}