问题 1426: [蓝桥杯][历届试题]九宫重排

题目描述
如下面第一个图的九宫格中,放着 1~8 的数字卡片,还有一个格子空着。与空格子相邻的格子中的卡片可以移动到空格中。经过若干次移动,可以形成第二个图所示的局面。
问题 1426: [蓝桥杯][历届试题]九宫重排_第1张图片
我们把第一个图的局面记为:12345678.
把第二个图的局面记为:123.46758
显然是按从上到下,从左到右的顺序记录数字,空格记为句点。
本题目的任务是已知九宫的初态和终态,求最少经过多少步的移动可以到达。如果无论多少步都无法到达,则输出-1。
输入
输入第一行包含九宫的初态,第二行包含九宫的终态。
输出
输出最少的步数,如果不存在方案,则输出-1。
样例输入
12345678.
123.46758
样例输出
3
思路:使用bfs+set判重(方法多种)这是最简单的。
用结构体保存初末状态步数,并且入队,向四个方向寻找下一个状态放到set集合(判重)和队列(bfs)中,一直找下去,直到找到末状态.

#include
#include
#include
#include
#include
#include
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=.=)

你可能感兴趣的:(蓝桥杯)