1.八数码 (搜索进阶 BFS)

八数码

题目链接

题目

在一个 \(3×3\) 的网格中,\(1∼8\)\(8\) 个数字和一个 \(X\) 恰好不重不漏地分布在这 \(3×3\) 的网格中。
例如:

1 2 3
X 4 6
7 5 8

在游戏过程中,可以把 X 与其上、下、左、右四个方向之一的数字交换(如果存在)。

我们的目的是通过交换,使得网格变为如下排列(称为正确排列):

1 2 3
4 5 6
7 8 X

例如,示例中图形就可以通过让 X 先后与右、下、右三个方向的数字交换成功得到正确排列。

交换过程如下:

1 2 3   1 2 3   1 2 3   1 2 3
X 4 6   4 X 6   4 5 6   4 5 6
7 5 8   7 5 8   7 X 8   7 8 X

把 X 与上下左右方向数字交换的行动记录为 u、d、l、r。

现在,给你一个初始网格,请你通过最少的移动次数,得到正确排列。

输入格式

输入占一行,将 3×3
的初始网格描绘出来。

例如,如果初始网格如下所示:

1 2 3 
x 4 6 
7 5 8 

则输入为:1 2 3 x 4 6 7 5 8

输出格式

输出占一行,包含一个字符串,表示得到正确排列的完整行动记录。

如果答案不唯一,输出任意一种合法方案即可。

如果不存在解决方案,则输出 unsolvable

输入样例:

2 3 4 1 5 x 7 6 8

输出样例

ullddrurdllurdruldr

思路

\(BFS\) 向上下左右四个方向扩展,注意将一维坐标与二维坐标的互相转换:$x=k/3,y=k%3 $

代码

#include<bits/stdc++.h>
using namespace std;
int dx[]={-1,0,1,0},dy[]={0,1,0,-1};

void bfs(string start)
{
	string op="urdl";
	queue<string>q;
	unordered_map<string,pair<int,string>>d;
	q.push(start);
	d[start].first=0;
	d[start].second="";
	string end="12345678x";
	
	while(q.size())
	{
		auto t=q.front();
		q.pop();	
		if(t==end)
		{
		    for(auto x:d[t].second)
		        cout<<x;
		    return;
		}
		int pos=t.find('x');
		
		int x=pos/3,y=pos%3;
		
		for(int i=0;i<4;i++)
		{
			int a=x+dx[i],b=y+dy[i];
			string tem=t;
			swap(tem[pos],tem[a*3+b]);
			if(a<0||a>=3||b<0||b>=3||d[tem].first)continue;
			d[tem].first=d[t].first+1;
			d[tem].second=d[t].second+op[i];
			q.push(tem);
		}
		
	}
	
	puts("unsolvable");
}
int main()
{
	char x;
	string str;
	for(int i=0;i<9;i++)
	{
		cin>>x;
		str+=x;
	}
	
	bfs(str);

	return 0;
}
posted @ 2023-05-03 16:13  风雨zzm  阅读(28)  评论(0编辑  收藏  举报