题目描述
如下面第一个图的九宫格中,放着 1~8 的数字卡片,还有一个格子空着。与空格子相邻的格子中的卡片可以移动到空格中。经过若干次移动,可以形成第二个图所示的局面。

我们把第一个图的局面记为:12345678.
把第二个图的局面记为:123.46758
显然是按从上到下,从左到右的顺序记录数字,空格记为句点。
本题目的任务是已知九宫的初态和终态,求最少经过多少步的移动可以到达。如果无论多少步都无法到达,则输出-1。
输入
输入第一行包含九宫的初态,第二行包含九宫的终态。
输出
输出最少的步数,如果不存在方案,则输出-1。
样例输入
12345678.
123.46758
样例输出
3
题目链接:https://www.dotcpp.com/oj/problem1426.html?sid=3582735&lang=1#editor
思路:BFS+unordered_map判重。
分析:题目乍一看是一个类似于走迷宫的题,但细看一下这道题与走迷宫是有些不同的。走迷宫是给出起点和终点,求起点到终点的最少步数,这道题也是求起点到终点的最少步数。
但是这道题是需要保证从起点走到终点后数字和给出的终态中的数字相同(例如图中样例起点到终点最少步数是3步,有两条路线1.空格->8->5->4 ;2.空格->6->5->4;只有走第一条路线才能使九宫格的终态符合题设要求)。九宫格的始态和终态是以字符串的格式给出的,所以我们在BFS的过程中也可以以字符串格式保存中间过程,这样的话,如果在BFS过程中出现了和终态一样的九宫格状态就说明存在最少步数,否则则不存在任何走法使九宫格始态变为终态。
那么如何变换九宫格的状态呢?
仔细观察样例图可以发现,当将任意一个数字移向空白块时,字符串中的.就会和对应的数字交换,可以根据这点来变换九宫格状态。
代码:
#include<bits/stdc++.h>
using namespace std;
typedef struct node
{
string state;
int step;
}node;
node start,End;
int dx[]={0,0,-1,1};
int dy[]={-1,1,0,0};
unordered_map<string,bool>s;
void bfs()
{
queue<node>q;
q.push(start);
while(!q.empty())
{
node t = q.front();
q.pop();
s[t.state]=true;
if(t.state==End.state)
{
cout<<t.step<<endl;
return ;
}
int x,y;
//找到.所在的位置
for(int i = 0; i < t.state.length();i++)
{
if(t.state[i]=='.')
{
x=i/3;
y=i%3;
break;
}
}
for(int i = 0;i<4;i++)
{
int xx = x+dx[i];
int yy = y+dy[i];
if(xx>=0&&xx<3&&yy<3&&yy>=0)
{
int pos = xx*3+yy;
int pospre = x*3+y;
string temp = t.state;
swap(temp[pospre],temp[pos]); #变换九宫格状态
if(!s.count(temp))
{
s[temp]=true;
q.push({temp,t.step+1});
}
}
}
}
cout<<-1<<endl;
return ;
}
int main()
{
cin>>start.state>>End.state;
bfs();
return 0;
}
3062



被折叠的 条评论
为什么被折叠?



