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

题目描述
如下面第一个图的九宫格中,放着 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=.=)

发布了14 篇原创文章 · 获赞 0 · 访问量 213

猜你喜欢

转载自blog.csdn.net/qq_43566782/article/details/104090432
今日推荐