分析:经典的八数码问题,参考别人的代码写的,逆向广搜,把结果保存起来,之后在使用。
#include<iostream> #include<queue> using namespace std; #define STATE_COUNT 363000 //因为9!=362880 int fact[]={1,1,2,6,24,120,720,5040,40320,362880}; //0到9的阶乘,用来计算hash值 char dir[4][2]={ {0,1},{0,-1},{1,0},{-1,0} //右,左,上,下 }; char dirchar[]="lrud"; //因为是从合法状态搜索出其他状态,方便之后返回时好处理,所以和搜索方向相反 class Eight_Puzzle { private: struct Node { char map[3][3]; char x_pos_x,x_pos_y; void GetMap(char* p); }; public: Eight_Puzzle(){} ~Eight_Puzzle(){} void Bfs(); //广度搜索打表 void OutPut(char* p); //根据状态输出结果 private: void OutPut(int hash); int Get_Hash(Node p); //获取某个状态的hash值 char m_path[STATE_COUNT]; bool m_vis[STATE_COUNT]; int m_pre[STATE_COUNT]; queue<Node> m_q; //搜索队列 }; void Eight_Puzzle::OutPut(int hash) { if(hash<=0) return ; printf("%c",m_path[hash]); OutPut(m_pre[hash]); } void Eight_Puzzle::OutPut(char* p) { Node tmp; int hash; tmp.GetMap(p); hash=Get_Hash(tmp); if(!m_vis[hash]) //表中无该hash值,说明状态不可达 { printf("unsolvable\n"); return ; } else if(hash==0) //标准状态,无需移动 { printf("\n"); return ; } else { OutPut(hash); printf("\n"); } } void Eight_Puzzle::Bfs() { char start[]="12345678x"; Node tmp; int i,x,y; int hash0,hash; memset(m_path,0,sizeof(m_path)); memset(m_vis,0,sizeof(m_vis)); memset(m_pre,0,sizeof(m_pre)); m_vis[0]=true; //起点设置为拜访 tmp.GetMap(start); m_q.push(tmp); //起始状态入队 while(!m_q.empty()) { tmp=m_q.front(); hash0=Get_Hash(tmp); //队头的hash,当前步 for(i=0;i<4;i++) { tmp=m_q.front(); //每次都重新取出队头 x=tmp.x_pos_x+dir[i][0]; y=tmp.x_pos_y+dir[i][1]; if(x<0 || y<0 || x>=3 || y>=3) continue; swap(tmp.map[tmp.x_pos_x][tmp.x_pos_y],tmp.map[x][y]); tmp.x_pos_x=x; //更新坐标 tmp.x_pos_y=y; hash=Get_Hash(tmp); if(m_vis[hash]) continue; m_vis[hash]=true; m_pre[hash]=hash0; m_path[hash]=dirchar[i]; m_q.push(tmp); } m_q.pop(); //队头出队,状态已处理 } } int Eight_Puzzle::Get_Hash(Node p) { char s[10]; int i,j,k,count; int hash=0; for(i=0;i<3;i++) for(j=0;j<3;j++) { count=0; s[i*3+j]=p.map[i][j]; for(k=i*3+j-1;k>=0;k--) if(s[k]>s[i*3+j]) count++; hash+=count*fact[i*3+j]; } return hash; } void Eight_Puzzle::Node::GetMap(char* p) { int i,j; i=j=0; while(*p) { if(*p>='1' && *p<='8' || *p=='x') { map[i][j]=*p; if(map[i][j]=='x') { map[i][j]='9'; x_pos_x=i; x_pos_y=j; } j++; if(j>=3) { i++; j=0; } } p++; } } int main() { char a[50]; Eight_Puzzle* eight_puzzle=(Eight_Puzzle*)new Eight_Puzzle; eight_puzzle->Bfs(); //打表,保存所有合法移动的步骤 while(gets(a)) { eight_puzzle->OutPut(a); } delete eight_puzzle; return 0; }
时间: 2024-10-03 07:49:57