题目描述
如下面第一个图的九宫格中,放着 1~8 的数字卡片,还有一个格子空着。与空格子相邻的格子中的卡片可以移动到空格中。经过若干次移动,可以形成第二个图所示的局面。
我们把第一个图的局面记为:12345678.
把第二个图的局面记为:123.46758
显然是按从上到下,从左到右的顺序记录数字,空格记为句点。
本题目的任务是已知九宫的初态和终态,求最少经过多少步的移动可以到达。如果无论多少步都无法到达,则输出-1。
输入
输入第一行包含九宫的初态,第二行包含九宫的终态。
输出
输出最少的步数,如果不存在方案,则输出-1。
样例输入
12345678.
123.46758
样例输出
3
思路:使用bfs+set判重(方法多种)这是最简单的。
用结构体保存初末状态步数,并且入队,向四个方向寻找下一个状态放到set集合(判重)和队列(bfs)中,一直找下去,直到找到末状态.
#include<cstdio>
#include<set>
#include<algorithm>
#include<string>
#include<queue>
#include<string.h>
using namespace std;
typedef struct node{
char origin[10];//多开一个存放0
char last[10];
int step;
}node;
set<string>vis;//判断是否访问过
queue<node>p;
node str;
int dir[4][2]={{0,1},{1,0},{0,-1},{-1,0}};
void bfs()
{
p.push(str);
while(!p.empty())
{
node head=p.front();
p.pop();
if(!strcmp(head.origin,head.last))//是否和末状态相同
{
printf("%d\n",head.step);
return ;
}
int pos;//寻找空格的位置
for(int i=0;head.origin[i]!='\0';i++)
if(head.origin[i]=='.')
{
pos=i;
break;
}
int x=pos/3;
int y=pos%3;
for(int i=0;i<4;i++)//向其他四个方向探寻
{
int x1=x+dir[i][0];
int y1=y+dir[i][1];
if(x1>=0&&x1<3&&y1>=0&&y1<3)
{
int pos1=x1*3+y1;//标注下一个状态空格所在的位置
node t=head;//临时变量
swap(t.origin[pos],t.origin[pos1]);//存储下一步的状态
if(!vis.count(t.origin))//判断该状态是否访问过
{
vis.insert(t.origin);
t.step++;
p.push(t);
}
}
}
}
printf("-1\n");
}
int main()
{
scanf("%s%s",str.origin,str.last);
str.step=0;
bfs();
return 0;
}
待更(方法不止一种0=.=)