AcWing 845. 八数码


/*y总写法,因为蓝桥杯不支持c++11,本题用map会超时,所以下面使用的是手写hash
#include <bits/stdc++.h>
using namespace std;
queue<string> q;
unordered_map<string,int> d;
int bfs(string start){
    string end="12345678x";
    
    q.push(start);
    d[start]=0;
    
    while(q.size()){
        string t=q.front();
        q.pop();
        int distance=d[t];
        int dx[4]={-1,0,1,0},dy[4]={0,-1,0,1};
        if(t==end) return distance;
        //状态转移,返回x在字符串中的下标
        int k=t.find('x');
        //计算出x在数组中的位置
        int x=k/3,y=k%3;
        for(int i=0;i<4;i++){
            int a=x+dx[i],b=y+dy[i];
            if(a>=0&&a<3&&b>=0&&b<3){
                //a*3+b数组中的位置转为字符串的位置
                //状态更新
                swap(t[k],t[a*3+b]);
                if(!d.count(t)){
                    d[t]=distance+1;
                    q.push(t);
                }
                //还原状态               
                swap(t[k],t[a*3+b]);
            }
        }
    }
    return -1;
}
int main(){
    string start;
    for(int i=0;i<9;i++){
        char c;
        cin>>c;
        start+=c;
    }
    cout<<bfs(start)<<endl;
    return 0;
}
*/
#include <iostream>
#include <queue>
#include <cstring>
//手写hash,把字符串转为数值,再根据数值找位置。再把数值赋给下标。
//https://www.acwing.com/solution/content/12584/
using namespace std;
struct node
{
    string map;
    int distance;
};
const int M=4e6+10,null=0x3f3f3f3f;
unsigned long long ha[9];
int h[M],b;
//哈希寻找对应坐标
int m_find(int x)
{
    int k=(x%M+M)%M;
    while(h[k]!=null&&h[k]!=x)
    {
        k++;
        if(k==M)k=0;
    }
    return k;
}
//字符串转化为唯一的序列,再通过序列求出在h数组中的下标
void s_to(string tmp){
    for(int i=1;i<10;i++)
        {
            char ccc=tmp[i];
            ha[i]=ha[i-1]*131+ccc;
        }
}
void bfs(string c)
{
    queue<node > q;
    q.push({c,0});
    string end="12345678x";
    //可移动的四个方向:上下左右
    int dx[]={0,0,1,-1},dy[]={1,-1,0,0};
    while(!q.empty())
    {
        node p=q.front();
        q.pop();
        
        //将字符串转为数值
        s_to(p.map);
        //把唯一的ha[9]赋值给通过哈希后寻找的h[下标]
        h[m_find(ha[9])]=ha[9];
        if(p.map==end)
        {
            cout<<p.distance<<endl;
            return ;
        }
        string k=p.map;
        int x=k.find('x')/3,y=k.find('x')%3;
        for(int i=0;i<4;i++)
        {
            int nx=x+dx[i];
            int ny=y+dy[i];
            if(nx>=0&&ny>=0&&nx<3&&ny<3){
                swap(p.map[x*3+y],p.map[nx*3+ny]);
                s_to(p.map);
            if(h[m_find(ha[9])]==null)
                q.push({p.map,p.distance+1});
            swap(p.map[x*3+y],p.map[nx*3+ny]);
            }
        }
    }
    cout<<"-1\n";
}
int main()
{
    memset(h,0x3f,sizeof h);
    string start;
    char c;
    for(int i=0;i<9;i++)
       {
           cin>>c;
           start+=c;
       }
    bfs(start);
    return 0;
}