AcWing 845. 八數碼
阿新 • • 發佈:2020-08-01
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; }