1571.八数码
时限:5000ms 内存限制:20000K 总时限:10000ms
描述
在九宫格里放在1到8共8个数字还有一个是空格,与空格相邻的数字可以移动到空格的位置,问给定的状态最少需要几步能到达目标状态(用0表示空格):
1 2 3
4 5 6
7 8 0
输入
输入一个给定的状态。
输出
输出到达目标状态的最小步数。不能到达时输出-1。
输入样例
1 2 3
4 0 6
7 5 8
输出样例
2
#include<iostream>
#include<queue>
#include<map>//用map来保存状态
using namespace std;
queue <int> q1;
map <int, int> smap;//map是用来存放一组一一映射关系的,在map中,一个x只能对应一个y
//移动的四个方向
int dr[4] = {0, 1, 0, -1};
int dc[4] = {-1, 0, 1, 0};
int readdata();
int bfs();
void init(int s);
int canmoveto(int u, int dire);
int moveto(int u, int dire);
int main()
{
int s, num;
s = readdata();
init(s);
num = bfs();
cout << num << endl;
return (0);
}
int readdata()
{
int i, s, num;
s = 0;
for(i = 0; i < 9; i++)//读取8数码的初始状态,变换成一串数保存
{
cin >> num;
s = s * 10 + num;
}
return(s);
}
void init(int s)
{
q1.push(s);
smap[s] = 0;
}
int bfs()
{
int i;
int u, v;
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(smap[u] + 1);
}
if(smap.count(v) == 0)//也就是说在map/set中不存在等价的两个(以上)元素,
//因此某个元素在map/set中出现的次数最多只能为1,用count得到的结果不是0就是
{
q1.push(v);
smap[v] = smap[u] + 1;//记录该条路径下的步数
}
}
}
}
return(-1);
}
int canmoveto(int u, int dire)//编码
{
/*用一串数来记录当前8数码的放置状态
*在该函数中通过逆变换将8数码的位置复现在9宫格中
*dire中保存了对0的操作方式
*返回0移动后的合法性*/
int i, j;
int b[3][3];//构造9宫格
int row, col;
int r, c;
int v;
v = u;
for(i = 2; i >= 0; i--)
{
for(j = 2; j >= 0; j--)
{
b[i][j] = v % 10;//将表示数码的数串的各位数从右往左逐个放在宫格里
v = v / 10;
if(b[i][j] == 0)
{
row = i;//记录空格的位置
col = j;
}
}
}
r = row + dr[dire];//根据dire的值来移动空格
c = col + dc[dire];
if(r >= 0 && r < 3 && c >= 0 && c < 3)//约束空格移动的范围
{
return(1);
}
else
{
return(0);
}
}
int moveto(int u, int dire)//解码
{
int i, j;
int b[3][3];
int row, col;
int r, c;
int v;
v = u;
for(i = 2; i >= 0; i--)
{
for(j = 2; j >= 0; j--)
{
b[i][j] = v % 10;
v = v / 10;
if(b[i][j] == 0)
{
row = i;
col = j;
}
}
}
r = row + dr[dire];
c = col + dc[dire];
b[row][col] = b[r][c];//交换 重新记录0在9宫格中的位置
b[r][c] = 0;//把该位置的数值置为0
v = 0;//将以9宫格状态存放的8数码复现成数串
for(i = 0; i < 3; i++)
{
for(j = 0; j < 3; j++)
{
v = v * 10 + b[i][j];
}
}
return(v);//返回变换后的8数码
}