八数码
题目
在一个 \(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;
}
标签:tem,网格,BFS,start,second,数码,first,string,进阶
From: https://www.cnblogs.com/zzmxj/p/17369204.html