#include<iostream>
#include<queue>
#include<map>
#include <cstdio>
using namespace std;
queue <int> q1;//记录状态
map <int, int> step;//记录步数
int dr[4] = {0, 1, 0, -1};
int dc[4] = {-1, 0, 1, 0};
int bfs();
bool canmoveto(int u, int dir);
int moveto(int u, int dir);
int main()
{
int n, ans;
scanf("%d", &n);
if(n == 123804765)
{//特殊情况
printf("0\n");
return 0;
}
q1.push(n);
step[n] = 0;
ans = bfs();
printf("%d\n", ans);
return (0);
}
int bfs()
{
int i, u, v;
while(!q1.empty())
{
u = q1.front();
q1.pop();
for(i = 0; i < 4; i++)
{
if(canmoveto(u, i))
{//如果能扩展
v = moveto(u, i);//v是u扩展的元素
if(v == 123804765)//如果v满足条件,就返回到达它的步数
return(step[u] + 1);
if(!step.count(v))//如果v是未被扩展的,就入队
{
q1.push(v);
step[v] = step[u] + 1;
}
}
}
}
return -1;
}
bool canmoveto(int u, int dir)
{
int i, j;
int b[3][3];
int row, col; //队首0的位置
int r, c; //由队首拓展的0的位置
for(i = 2; i >= 0; i--)
{
for(j = 2; j >= 0; j--)
{
b[i][j] = u % 10;
u /= 10;
if(!b[i][j]) row = i, col = j;
}
}
r = row + dr[dir];
c = col + dc[dir];
if(r >= 0 && r < 3 && c >= 0 && c < 3)
return 1;
return 0;
}
int moveto(int u, int dir)
{
int i, j;
int b[3][3];
int row, col;
int r, c;
int v;
for(i = 2; i >= 0; i--)
{
for(j = 2; j >= 0; j--)
{
b[i][j] = u % 10;
u /= 10;
if(!b[i][j]) row = i, col = j;
}
}
r = row + dr[dir];
c = col + dc[dir];
b[row][col] = b[r][c];
b[r][c] = 0;
v = 0;
for(i = 0; i < 3; i++)
for(j = 0; j < 3; j++)
v = v * 10 + b[i][j];
return v;
}
洛谷P1379_八数码游戏
最新推荐文章于 2023-03-23 22:19:41 发布