1. 程式人生 > 實用技巧 >AcWing 845. 八數碼

AcWing 845. 八數碼

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;
}