<pre name="code" class="cpp">#include<iostream> #include<cstring> #include<string> #include<set> #include<vector> #include<queue> #include<cstdio> #include<cmath> #include<algorithm> using namespace std; typedef int State[9]; const int maxn=1000000; State st[maxn],goal; //相当于st[maxn][9]保存走的每一步下的8个数字的;goal[9]保存目标; int dist[maxn]; //距离,即走了几步; const int dx[]={1,-1,0, 0}; const int dy[]={0, 0,1,-1}; bool inside(int x,int y) { <span style="white-space:pre"> </span>return x>=0&&x<3&&y>=0&&y<3; } int bfs() { init_table(); int front=1,rear=2; while(front<rear) //就相当于queue { State& s=st[front]; //s就是st[front]的地址; if(!memcmp(s,goal,sizeof(s))) return front; int z; for(z=0;z<9;z++) if(!s[z]) break; int x=z/3,y=z%3; for(int i=0;i<4;i++) //先走4步试试 { int nx=dx[i]+x; int ny=dy[i]+y; int nz=nx*3+ny; if(inside(nx,ny)) //如果是合法的移动 { State& t=st[rear]; memcpy(t,s,sizeof(s)); t[nz]=s[z]; t[z]=s[nz]; //保存rear这一步的状态 dist[rear]=dist[front]+1; //这一步的步数是上一步的+1; if(try_to_insert(rear)) rear++; //判断这是否已经走过,若走过就走另一种路,并将其覆盖 } } front++; //front是判断每走的一步是否到达goal } } int main() { for(int i=0;i<9;i++) cin>>st[1][i]; for(int i=0;i<9;i++) cin>>goal[i]; int idx=bfs(); cout<<dist[idx]; return 0; }
关键是判重: 1)STL的set set<int> lookup; void init_table() { <span style="white-space:pre"> </span>lookup.clear(); } bool try_to_insert(int n) { int sum=0; State& t=st[n]; for(int i=0;i<9;i++) sum=t[i]+sum*10; if(lookup.count(sum)) return false; lookup.insert(sum); return true; }
2)Hash表 const int Hashsize=1000003; int Head[maxn],next[maxn]; void init_table() { memset(Head,0,sizeof(Head)); memset(next,0,sizeof(next)); } int Hash(int n) //将9个数映射为符合Hashsize的数 { int v=0; State& t=st[n]; for(int i=0;i<9;i++) v=t[i]+v*10; return v % Hashsize; } bool try_to_insert(int s) { int h=Hash(s); int u=Head[h]; // Head[h]保存st[s]中同样的Hash数的最前面的s位置 while(u) //非零就说明以前遇到过同样的hash值 { if(!memcmp(st[s],st[u],sizeof(st[u]))) return false; u=next[u]; //next指向同样的hash数的前一个s值 } next[s]=Head[h]; //当前s这一步指向下一个同样的hash数的s值即Head[h]; Head[h]=s; //当前hash数h指向s这一步,即更新到同样的Hash数的最前面的s位置; return true; }