晚点更
________________________
八数码问题也称为九宫问题。在3×3的棋盘,摆有八个棋子,每一个棋子上标有1至8的某一数字,不同棋子上标的数字不同样。棋盘上另一个空格,与空格相邻的棋子能够移到空格中。要求解决的问题是:给出一个初始状态和一个目标状态,找出一种从初始转变成目标状态的移动棋子步数最少的移动步骤。所谓问题的一个状态就是棋子在棋盘上的一种摆法。棋子移动后,状态就会发生改变。解八数码问题实际上就是找出从初始状态到达目标状态所经过的一系列中间过渡状态。
——————————————
八数码问题的解法有很多 其实就是 从一种状态经过几步到达另一种状态的题型,和跳蚱蜢一样 。这里依旧采用 bfs+set去重,个人感觉比康托展开好用
先上代码
#include<bits/stdc++.h> using namespace std; int ans[3][3],sum=-1; struct node { int a[3][3]; int x,y,step; } s; int dir[4][2]= {{1,0},{-1,0},{0,1},{0,-1}}; set<int>se; queue<node>q; bool check() { for(int i=0; i<3; i++) for(int j=0; j<3; j++) if(s.a[i][j]!=ans[i][j]) return false; return true; } bool in(int x,int y) { if(x>=0&&x<3&&y>=0&&y<3) return true; return false; } bool f(int x,int y) { int pp=0; for(int i=0,k=1; i<3; i++) for(int j=0; j<3; j++) { if(i==x&&j==y) pp=pp*10; else pp=pp*10+s.a[i][j]; if(!s.a[i][j]) pp+=s.a[x][y]; } if(se.count(pp)) return false; se.insert(pp); return true; } void bfs() { while(!q.empty()) { s=q.front(); q.pop(); if(check()) { sum=s.step; break; } for(int i=0; i<4; i++) { int newx=s.x+dir[i][0]; int newy=s.y+dir[i][1]; if(!in(newx,newy)) continue; if(!f(newx,newy)) continue; node t=s; swap(t.a[t.x][t.y],t.a[newx][newy]); t.x=newx,t.y=newy,t.step=s.step+1; q.push(t); } } } int main() { int t; int p=0; for(int i=0,k=1; i<3; i++) for(int j=0; j<3; j++) { scanf("%d",&s.a[i][j]); p=p*10+s.a[i][j]; if(s.a[i][j]==0) s.x=i,s.y=j,s.step=0; } for(int i=0; i<3; i++) for(int j=0; j<3; j++) scanf("%d",&ans[i][j]); se.insert(p); q.push(s); bfs(); if(sum<0) printf("Impossible\n"); else printf("%d\n",sum); }