这道题如同难度一样,确实不好上手,既然求最短路径,直接bfs就好,但是bfs的核心就是标记,我们该怎么标记一个字符串呢,我们发现这个字符串很特殊,我们标记的只有这个字符串的全排列,然后我也是学到了一个康托的一个算法,然后我就去看了一下,在长长的代码下,还是AC了,最难的点就是怎么把字符串哈希,可能蓝桥杯好像可以用map,map的时间效率明显很低。
不多说
代码如下。
#include<iostream>
#include<string.h>
#include<queue>
#include<algorithm>
using namespace std;
const int N=362880;
bool book[N];
struct point
{
int x;
int y;
int foot;
char p[10];
};
int fact[10];
char mod[10],k[10];
int dx[4]={0,0,1,-1},dy[4]={1,-1,0,0};
int hash_cal(char s[])//对字符串哈希的一个算法,最难的点
{
int cnt=0,ans=0;
for(int i=0;i<9;i++)
{
cnt=0;
for(int j=0;j<i;j++)
{
if(s[j]>s[i])
cnt++;
}
ans+=cnt*fact[i];
}
return ans;
}
int bfs(int st)
{
queue<point> q;
point k,z;
k.x=st/3;
k.y=st%3;
k.foot=0;
strcpy(k.p,mod);
q.push(k);
while(q.size())
{
k=q.front();
q.pop();
int sx=k.x,sy=k.y;
for(int i=0;i<4;i++)
{
int tx=sx+dx[i];
int ty=sy+dy[i];
if(0<=tx&&0<=ty&&tx<=2&&ty<=2)
{
char rev[10];
strcpy(rev,k.p);
rev[k.x*3+k.y]=rev[tx*3+ty];
rev[tx*3+ty]='x';
if(!strcmp(rev,"12345678x"))
return k.foot+1;
if(!book[hash_cal(rev)])
{
book[hash_cal(rev)]=true;
z.x=tx;
z.y=ty;
strcpy(z.p,rev);
z.foot=k.foot+1;
q.push(z);
}
}
}
}
return -1;
}
int main(void)
{
fact[0]=1;
for(int i=1;i<9;i++) fact[i]=i*fact[i-1];
char op[2];
int st;
for(int i=0;i<9;i++)
{
scanf("%s",op);
if(op[0]=='x') st=i;
mod[i]=op[0];
}
mod[9]=0;
cout<<bfs(st)<<endl;
}