#include<iostream>
#include<queue>//用队列解决广搜的问题
#include <map>//解决队列中两个问题 1.count是否重复 2.用较小的内存存储较大的数组
using namespace std ;
queue<int>q1 ;
map<int,int>step ;//用较小的内存存储较大的数组
int num = 0 ;
int dr[4] = {0 , 1 , 0 , -1} ;//左、下、右、上
int dc[4] = {-1 , 0 , 1 , 0} ;
int bfs() ;//广搜
int canmoveto(int u , int dire) ;//是否可以移动
int moveto(int u , int dire) ;//移动后的状态
int main()
{
int m , i , num1 ;
for(i = 1 ; i <= 9 ; i++)//读入数据
{
cin >> m ;
num = num * 10 + m ;
}
q1.push(num) ;//入队
step[num] = 0 ;//初状态步数为0
num1 = bfs() ;//输出广搜的结果
}
int bfs()
{
int u , v , i;
while(!q1.empty())//队列非空 格式
{
u = q1.front() ;//访问队首元素
q1.pop() ;//出队
for(i = 0 ; i < 4 ; i++)
{
if(canmoveto(u,i))//判断是否可以移动
{
v = moveto(u , i);//移动后的状态
if(v == 123456780)//判断是否符合要求
{
return (step[u] + 1) ;//返回步数
}
if (step.count(v) == 0)//是否重复 这是map的作用
{
q1.push(v) ;//新状态入队
step[v] = step[u] + 1 ;//步数+1
}
}
}
}
return -1 ;//没有解返回-1
}
int canmoveto(int u , int dire)
{
int i , j , row , col , r , c , b[3][3] ;
for(i = 2 ; i >= 0 ; i--)//将数字变为二维数组进行移动操作
{
for(j = 2 ; j >= 0 ; j--)
{
b[i][j] = u % 10 ;
u /= 10 ;
if(b[i][j] == 0)
{
row = i ;
col = j ;
}
}
}
r = row + dr[dire] ;
c = col + dc[dire] ;
if(r >= 0 && r < 3 && j >= 0 && j < 3)//判断是否可以移动
{
return 1 ;
}
else
{
return 0 ;
}
}
int moveto(int u , int dire)
{
int i , j , row , col , r , c , m , b[3][3] , v = 0 ;
for(i = 2 ; i >= 0 ; i--)//将数字变为二维数组进行移动操作
{
for(j = 2 ; j >= 0 ; j--)
{
b[i][j] = u % 10 ;
u /= 10 ;
if(b[i][j] == 0)//找到空格并记录
{
row = i ;
col = j ;
}
}
}
r = row + dr[dire] ;
c = col + dc[dire] ;
b[row][col] = b[r][c] ;//空格转换达到新状态
b[r][c] = 0 ;
for(i = 0 ; i <= 2 ; i++)
{
for(j = 0 ; j <= 2 ; j++)
{
v = v * 10 + b[i][j] ;
}
}
return v ;
}