Solution
题意非常明确,显然搜索,搜索的时候存储八数码可以用二维或者一维,但是个人感觉用二维更明了一些。
需要注意去重,去重可以用set维护一下已经搜过的八数码,如果手写去重小心MLE
具体实现的时候注意一下细节。
Code
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <queue>
#include <string>
#include <set>
#define N 10010
using namespace std;
set <string> s;
typedef pair<int,int> PAIR;
int dx[4] = {0,0,1,-1};
int dy[4] = {1,-1,0,0};
int startt[5][5] ;
int cnt = 0;
struct Node
{
int a[5][5];
int vis;
};
PAIR get_zero(int a[5][5])
{
for(int i=1;i<=3;i++)
{
for(int j=1;j<=3;j++) if(!a[i][j]) return PAIR(i,j);
}
}
bool get_ans(int a[5][5])
{
string chk;
for(int i=1;i<=3;i++)
{
for(int j=1;j<=3;j++) chk += (a[i][j] + '0');
}
if(chk == "123804765") return true;
else return false;
}
void bfs()
{
queue <Node> q;
Node inp;
for(int i=1;i<=3;i++)
{
for(int j=1;j<=3;j++) inp.a[i][j] = startt[i][j];
}
inp.vis = 0;
q.push(inp);
while(!q.empty())
{
Node p = q.front();
q.pop();
PAIR zero_add = get_zero(p.a);
if(get_ans(p.a))
{
cout<<p.vis<<endl;
return;
}
for(int i=0;i<4;i++)
{
int ax = zero_add.first + dx[i]; //找到当前为0的点
int ay = zero_add.second + dy[i];
if(ax>=1&&ax<=3&&ay>=1&&ay<=3) //如果不越界
{
int t[5][5];
for(int j=1;j<=3;j++)//获得修改后的map
{
for(int k=1;k<=3;k++) t[j][k] = p.a[j][k];
}
t[zero_add.first][zero_add.second] = t[ax][ay];
t[ax][ay] = 0;
string pp;//转换成string与set内比较,去重操作
for(int i=1;i<=3;i++) for(int j=1;j<=3;j++) pp += (char)t[i][j] +'0';
if(!s.count(pp)) //如果不重复,即当前map没有被搜过
{
Node psh;
s.insert(pp);//将当前map加入set
for(int j=1;j<=3;j++) //入队
{
for(int k=1;k<=3;k++) psh.a[j][k] = t[j][k];
}
psh.vis = p.vis + 1;
q.push(psh);
}
}
}
}
}
int main()
{
for(int i=1;i<=3;i++)
{
for(int j=1;j<=3;j++)
{
scanf("%1d",&startt[i][j]);
}
}
bfs();
}
具体实现码量稍大,细节很多,比如将八数码转换成string放入set维护去重,具体存八数码二维数组即可,用string存操作更困难。
标签:set,int,Luogu,二维,数码,&&,P1379,include,刷题 From: https://www.cnblogs.com/SXqwq/p/17489195.html