[C++]九宫重排
九宫重排:
如下面第一个图的九宫格中,放着 1~8 的数字卡片,还有一个格子空着。与空格子相邻的格子中的卡片可以移动到空格中。经过若干次移动,可以形成第二个图所示的局面。
我们把第一个图的局面记为:12345678.
把第二个图的局面记为:123.46758
显然是按从上到下,从左到右的顺序记录数字,空格记为句点。
本题目的任务是已知九宫的初态和终态,求最少经过多少步的移动可以到达。如果无论多少步都无法到达,则输出-1
输入格式:
输入第一行包含九宫的初态,第二行包含九宫的终态。
输出格式:
输出最少的步数,如果不存在方案,则输出-1。
输入:
12345678.
123.46758
输出:
3
解题思路:可以使用bfs,由于时间限制,需要使用双向bfs,对初态和终态进行bfs,当两边状态变化到一种形态时,表示可以达到。即maps值为1,是由初态变化而来,为2的话,是由终态变化而来。当maps值相加为3的时候,则证明初态和终态都能达到此状态。
#include<iostream>
#include<map>
#include<queue>
#include<string>
using namespace std;
int ne[4][2] = {1,0,-1,0,0,1,0,-1};
map<string, int> maps;
map<string, int> temp;
string a, b;
/*
双向bfs
*/
int bfs(){
if(a == b)
return 0;
queue<string> que;
que.push(a);
que.push(b);
while(!que.empty()) {
string head = que.front();
que.pop();
char t;
int x, y;
for(int i = 0; i<3; i++){
for(int j = 0; j<3; j++){
t = i*3+j;
if(head[t] == '.'){
x = i;
y = j;
break;
}
}
}
t = x*3+y;
for(int i = 0; i<4; i++){
int nx = x + ne[i][0];
int ny = y + ne[i][1];
if(nx>=0 && nx<3 && ny>=0 && ny < 3){
string tail = head;
tail[t] = head[nx*3+ny];
tail[nx*3+ny] = head[t];
if(!maps[tail]) {
maps[tail] = maps[head]; //区分由a转化而来还是由b转化而来
temp[tail] = temp[head]+1; //移动步数加1
que.push(tail);
}
else if(maps[tail] + maps[head] == 3){
return temp[tail]+temp[head]+1;
}
}
}
}
return -1;
}
int main(){
cin>>a>>b;
/**
初始化 由a转化而来的maps值为1 由b转化来的maps值为2
*/
maps[a] = 1;
maps[b] = 2;
cout<<bfs()<<endl;
return 0;
}