试题 历届试题 九宫重排
资源限制
时间限制:1.0s 内存限制:256.0MB
问题描述
如下面第一个图的九宫格中,放着 1~8 的数字卡片,还有一个格子空着。与空格子相邻的格子中的卡片可以移动到空格中。经过若干次移动,可以形成第二个图所示的局面。
我们把第一个图的局面记为:12345678.
把第二个图的局面记为:123.46758
显然是按从上到下,从左到右的顺序记录数字,空格记为句点。
本题目的任务是已知九宫的初态和终态,求最少经过多少步的移动可以到达。如果无论多少步都无法到达,则输出-1。
输入格式
输入第一行包含九宫的初态,第二行包含九宫的终态。
输出格式
输出最少的步数,如果不存在方案,则输出-1。
样例输入
12345678.
123.46758
样例输出
3
样例输入
13524678.
46758123.
样例输出
22
#include <bits/stdc++.h>
using namespace std;
char begin[3][3],end[3][3];
int move[4][2] = {1,0,-1,0,0,1,0,-1};
map<int,int> map_1;
struct node{
int step;
char ch[3][3];
node(int step_init,char ch_init[3][3]){
step = step_init;
for(int i = 0;i < 3;i++)
for(int j = 0;j < 3;j++)
ch[i][j] = ch_init[i][j];
}
};
int book(char str[3][3]){//每一种状态都对应一个数
int result = 0;
for(int i=0;i<3;i++){
for(int j=0;j<3;j++){
if(str[i][j] != '.')
result = result*10+(str[i][j]-'0');
else
result = result*10+9;
}
}
return result;
}
bool check(char str[3][3]){//检查是否到达结束状态
for(int i = 0;i < 3;i++){
for(int j = 0;j < 3;j++){
if(str[i][j] != end[i][j]){
return false;
}
}
}
return true;
}
int bfs(){
int res = -1;
queue<node> q;
q.push(node(0,begin));
map_1[book(q.front().ch)] = 1;
while(!q.empty()){
node n1 = q.front();
q.pop();
int x = -1,y = -1;
for(int i = 0;i < 3;i++){
for(int j = 0;j < 3;j++){
if(n1.ch[i][j] == '.'){
x = i;
y = j;
break;
}
}
if(x != -1 && y != -1) break;
}
for(int i = 0;i < 4;i++){
node n2 = n1;
int xx = x + move[i][0];
int yy = y + move[i][1];
if(xx < 0 || yy < 0 || xx == 3 || yy == 3) continue;
swap(n2.ch[xx][yy],n2.ch[x][y]);
if(map_1[book(n2.ch)] == 1) continue;
map_1[book(n2.ch)] = 1;
n2.step = n1.step + 1;
if(check(n2.ch) == true){
res = n2.step;
return res;
}
q.push(n2);
}
}
return res;
}
int main(){
string str1,str2;
cin>>str1>>str2;
int index = 0;
for(int i = 0;i < 3;i++)
{
for(int j = 0;j < 3;j++)
{
begin[i][j] = str1[index];
end[i][j] = str2[index];
index++;
}
}
int res = bfs();
cout<<res<<endl;
return 0;
}