如代码,注释的很清楚了
单向的还可以看看这个https://blog.csdn.net/qq_42971794/article/details/87869292
以下是参考上面连接的双向
#include<iostream>
#include<algorithm>
#include<queue>
#include<map>
#include<string>
using namespace std;
int dr[][2] = { 0,1,0,-1,1,0,-1,0 };
queue<int> q1, q2;
map<int, int> c1; //记录是否走过这个状态,避免重复,
map<int, int> c2; //记录到这个状态需要走多少步
int init(int map[3][3]) {
int ans = 0;
for (int i = 0; i <3; ++i) {
for (int j = 0; j<3; ++j) {
ans = ans * 10 + map[i][j];
}
}
return ans;
}
int main() {
int first;
int ans;
int mapp[3][3];
for (int i = 0; i < 3; ++i)
for (int j = 0; j < 3; ++j)
cin >> mapp[i][j];
first = init(mapp);
for (int i = 0; i < 3; ++i)
for (int j = 0; j < 3; ++j)
cin >> mapp[i][j];
ans = init(mapp);
q1.push(first);
c1[first] = 1;//说明first这个状态访问过,以后遇到就不用继续 访问了。 并且用1表示是从正向bfs访问的。
c2[first] = 0;//first是初始状态,只需要0步就可以到达。
q2.push(ans);
c1[ans] = 2;//2表示是从后面开始访问得到的结点。
c2[ans] = 0;//同上
bool is;
while (!q1.empty() || !q2.empty()) {
int begin, x, y; //x,y表示空格的位置
if (q1.size() < q2.size() || q2.empty()) {
begin = q1.front();
q1.pop();
is = true;
}
else {
begin = q2.front();
q2.pop();
is = false;
}
int k = begin;
for (int i = 2; i >= 0; --i)
for (int j = 2; j >= 0; --j)
{
mapp[i][j] = k % 10;
k /= 10;
if (mapp[i][j] == 0) {
x = i;
y = j;
}
}
for (int i = 0; i < 4; ++i) {
int x_new = x + dr[i][0];
int y_new = y + dr[i][1];
if (x_new >= 0 && x_new < 3 && y_new >= 0 && y_new < 3) {
swap(mapp[x][y], mapp[x_new][y_new]);
int temp = init(mapp);
if (c1[temp] == c1[begin]) //说明与之前的状态有重复,故不再继续以此状态bfs;
{
swap(mapp[x][y], mapp[x_new][y_new]);
continue;
}
if (c1[temp] + c1[begin] == 3) {
cout << c2[temp] + c2[begin] + 1;
return 0;
}
c2[temp] = c2[begin] + 1; //否则就继续bfs,则多走了1步
c1[temp] = c1[begin]; //按照之前的bfs标记。
if (is == true) {
q1.push(temp);
}
else q2.push(temp);
swap(mapp[x][y], mapp[x_new][y_new]); //回到循环开始的状态,继续所有该层。这个别忘记了!一定要复原。
}
}
}
return 0;
}