参考:https://blog.csdn.net/weirdo_coder/article/details/89167900
并给出了自己的一些更改,提高了可读性,降低了算法效率。
#include<cstdio>
#include<map>
#include<algorithm>
#include<queue>
using namespace std;
struct Node{
int M[3][3]; // 棋盘本身
int x0 = -1, y0 = -1; // 存储0的位置
int step = -1;
};
int to_mirror(int m[3][3]){
int target_mirror = 0;
for(int i = 0; i < 3 ; i ++){
for(int j = 0; j < 3; j ++){
target_mirror *= 10;
target_mirror += m[i][j];
}
}
return target_mirror;
}
// 这个函数没有用到 可以不看
void to_m(int mirror, Node *n){
for(int i = 2; i >= 0; i --){
for(int j = 2; j >= 0; j --){
int target = mirror % 10;
n -> M[i][j] = target;
mirror /= 10;
}
}
}
map<int, bool> bfs_map;
Node start_m, end_m;
queue<Node> Q;
// 这是增量数组
// 按照胡凡《算法笔记》上的套路,就应该按真实的上下左右设置增量数组
// 这样比较简单,易懂
int X[4] = {0, -1, 0, 1};
int Y[4] = {-1, 0, 1, 0};
// 判断一个点是否合法
bool judge(int x, int y){
if(x > 2 || y > 2 || x < 0 || y < 0){
return false;
}
return true;
}
// 实际交换0和其他值的函数
void change(Node* n, int change_x, int change_y){
swap(n -> M[n -> x0][n -> y0], n -> M[n -> x0 + change_x][n -> y0 + change_y]);
n -> x0 += change_x;
n -> y0 += change_y;
}
int main(){
// 读入
for(int i = 0; i < 3; i++){
for(int j = 0; j < 3; j++){
scanf("%d", &(start_m.M[i][j]));
if(start_m.M[i][j] == 0){
start_m.x0 = i;
start_m.y0 = j;
}
}
}
start_m.step = 1; // 题目要求走start的步数为1
for(int i = 0; i < 3; i++){
for(int j = 0; j < 3; j++){
scanf("%d", &(end_m.M[i][j]));
if(end_m.M[i][j] == 0){
end_m.x0 = i;
end_m.y0 = j;
}
}
}
int end_mirror = to_mirror(end_m.M);
if(to_mirror(start_m.M) == end_mirror){
printf("1");
return 0;
}
Q.push(start_m);
bfs_map[to_mirror(start_m.M)] = true;
while(!Q.empty()){
Node tnode = Q.front();
Q.pop();
for(int i = 0; i < 4; i ++){
Node tmp = tnode;
// 取增量
int change_x = X[i];
int change_y = Y[i];
// 判断当前能不能换
if(judge(tmp.x0 + change_x, tmp.y0 + change_y)){
// 换
change(&tmp, change_x, change_y);
// 判断当前状态有没有换过
int tmp_mirror = to_mirror(tmp.M);
if(!bfs_map[tmp_mirror]){
bfs_map[tmp_mirror] = true;
tmp.step ++;
if(tmp_mirror == end_mirror){
end_m.step = tmp.step;
break;
}
Q.push(tmp);
}
}
}
}
printf("%d", end_m.step);
return 0;
}