题意:经典八数码问题
思路:双向bfs
ps:还有a*算法(还不会)等解法。
代码:
#include<iostream> #include<stdio.h> #include<string.h> #include<queue> using namespace std; #define MAXN 362885//最多组合个数:9!=362880 int dir[4]={-3,3,-1,1};//4个方向移动:u,d,l,r char opF[4]={'u','d','l','r'};//正向bfs操作 char opR[4]={'d','u','r','l'};//反向bfs操作 int fac[9]={1,1,2,6,24,120,720,5040,40320};//阶乘 bool visF[MAXN];//正向访问标志 bool visR[MAXN];// string sTarg="123456789";//目标棋盘 struct node{//存储棋盘信息 string s;//当前棋盘 int xLoca;//x位置 }t; struct node2{//存储操作 int idF,idR;//正向前驱、反向前驱 char cF,cR;//操作 }op[MAXN]; int cantor_hash(string s){//康托展开,一共n位 int n=9;//共9位 int i,j,temp,num; num=0; for(i=0;i<n-1;i++){//n为位数 temp=0; for(j=i+1;j<n;j++){ if(s[j]<s[i])temp++; } num+=fac[n-(i+1)]*temp; } return num;//从0开始 } void display(int i){//输出正向操作 if(op[i].idF==-1)return; display(op[i].idF); printf("%c",op[i].cF); } void dBfs(){ queue<node>qF,qR;//正向队列,反向队列 node tmp1,tmp2;//棋盘状态临时变量 int id_hash,id_hash2,xLoca,i;//id 康托哈希下标值,xLoca 暂存x位置 tmp1=t;//初始状态 tmp2.s=sTarg;//目标状态 tmp2.xLoca=8;//目标状态x位置 id_hash=cantor_hash(tmp1.s);//初始状态 visF[id_hash]=true; op[id_hash].idF=-1; qF.push(tmp1); id_hash=cantor_hash(tmp2.s);//目标状态 visR[id_hash]=true; op[id_hash].idR=-1; qR.push(tmp2); while(!qF.empty()&&!qR.empty()){ //正向bfs tmp1=qF.front(); qF.pop(); id_hash=cantor_hash(tmp1.s); if(visR[id_hash]){//反向bfs也访问过 display(id_hash); id_hash2=id_hash; while(op[id_hash2].idR!=-1){ printf("%c",op[id_hash2].cR); id_hash2=op[id_hash2].idR; } printf(" "); return; } for(i=0;i<4;++i){ if(i==0&&tmp1.xLoca<3)continue; if(i==1&&tmp1.xLoca>5)continue; if(i==2&&tmp1.xLoca%3==0)continue; if(i==3&&tmp1.xLoca%3==2)continue; xLoca=tmp1.xLoca+dir[i]; tmp2=tmp1; swap(tmp2.s[tmp1.xLoca],tmp2.s[xLoca]); id_hash2=cantor_hash(tmp2.s); if(!visF[id_hash2]){ visF[id_hash2]=true; tmp2.xLoca=xLoca; op[id_hash2].idF=id_hash; op[id_hash2].cF=opF[i]; qF.push(tmp2); } } //反向bfs tmp1=qR.front(); qR.pop(); id_hash=cantor_hash(tmp1.s); if(visF[id_hash]){//正向bfs也访问过 display(id_hash); id_hash2=id_hash; while(op[id_hash2].idR!=-1){ printf("%c",op[id_hash2].cR); id_hash2=op[id_hash2].idR; } printf(" "); return; } for(i=0;i<4;++i){ if(i==0&&tmp1.xLoca<3)continue; if(i==1&&tmp1.xLoca>5)continue; if(i==2&&tmp1.xLoca%3==0)continue; if(i==3&&tmp1.xLoca%3==2)continue; xLoca=tmp1.xLoca+dir[i]; tmp2=tmp1; swap(tmp2.s[tmp1.xLoca],tmp2.s[xLoca]); id_hash2=cantor_hash(tmp2.s); if(!visR[id_hash2]){ visR[id_hash2]=true; tmp2.xLoca=xLoca; op[id_hash2].idR=id_hash; op[id_hash2].cR=opR[i]; qR.push(tmp2); } } } } int main(){ char str[32];//串 int len;//串长度 int i,j,k;//k 第几个数码 int ivsNum;//逆序数 while(~scanf("%[^ ]",str)){ getchar();//吸收回车 memset(visF,false,sizeof(visF)); memset(visR,false,sizeof(visR)); len=strlen(str); t.s=""; k=0;//第几个数码 for(i=0;i<len;++i){//处理字符串 if(str[i]!=' '){ if(str[i]=='x'){ t.s=t.s+'9'; t.xLoca=k; } else t.s=t.s+str[i]; ++k;// } } ivsNum=0;//逆序数初始为0 for(i=0;i<9;++i){ if(t.s[i]=='9')continue; for(j=0;j<i;++j){ if(t.s[j]=='9')continue; if(t.s[j]>t.s[i])++ivsNum; } } if(ivsNum&1)printf("unsolvable ");//逆序数为奇数 else dBfs();//双向bfs } return 0; }