题目大意:将八数码的形式转变为最终形式所需要的步骤
解题思路:最终形式只有一种,可以用最终形式反向bfs推出可以变成那些八数码,标记并记录路径,对于每一种形式用康托展开来表示
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#include<iostream> #include<queue> using namespace std; int a[10],fac[10]; int d[4][2]={1,0,-1,0,0,1,0,-1}; struct node1 { char way;//记录路径 int fath;//记录父节点 }Node[370000]; struct node2{ int b[10];//记录当前序列 int n,son;//x在序列中的位置,当前康托值 }; void cal_fac(){//计算阶乘 fac[0]=fac[1]=1; for(int i=2;i<=8;i++) fac[i]=fac[i-1]*i; } int cantor(int aa[]){//康托展开 int ans=0,k=0; for(int i=0;i<9;i++){ k=0; for(int j=i+1;j<9;j++){ if(aa[i]>aa[j]) k++; } ans+=k*fac[8-i]; } return ans; } void bfs(int a[]){ queue<node2>Q; node2 q; for(int i=0;i<9;i++) q.b[i]=a[i]; q.n=8;q.son=0; Node[q.son].fath=0;//最终点的父节点置为自身 Q.push(q); while(!Q.empty()){ q=Q.front();Q.pop(); for(int i=0;i<4;i++){ node2 p=q; int tx=p.n%3,ty=p.n/3; tx+=d[i][0],ty+=d[i][1]; if(tx>=0&&tx<3&&ty>=0&&ty<3){ p.n=ty*3+tx;//更新x的位置 swap(p.b[p.n],p.b[q.n]);//交换移动位置的值 p.son=cantor(p.b); if(Node[p.son].fath==-1){//若该康托值未被访问过 Node[p.son].fath=q.son; if(i==0) Node[p.son].way='l';//反向bfs,记录反着来即可 else if(i==1) Node[p.son].way='r'; else if(i==2) Node[p.son].way='u'; else if(i==3) Node[p.son].way='d'; Q.push(p); } } } } } int main(){ for(int i=0;i<370000;i++){ Node[i].fath=-1; } for(int i=0;i<9;i++) a[i]=i+1; cal_fac(); bfs(a); char ch[20]; int t[10]; while(gets(ch)>0){ for(int i=0,j=0;ch[i]!='