poj 1077 八数码难题

来源:互联网 发布:艾瑞德生物科技知乎 编辑:程序博客网 时间:2024/05/15 00:27

终于自己AC了这道八数码难题,用的方法是最最普通的单项BFS+Hash,这里主要的难点在于如何保存状态,其实,在八数码里所有的状态共有9!种=362880种,所以在每个转台节点,我需要一个char state[3][3]来记录当前棋盘的状态,用一个int x,y来记录当前x的位置,用char operation来记录从父状态到这个状态需要进行的操作,当然,为了记录路径,我需要记录它的父节点,然而这个父节点要怎么去记录呢,刚开始的时候对于这个问题纠结了很久,曾经直接把结构体存在队列里面,然后用指针去引用它的父节点,殊不知,当出队操作后,声明的节点就是去了意义,所以这种做法是错误的。看了别人的思路,把所有的状态节点都存在一个结构体数组里面,并且用一个count记录当钱数组里面状态的个数,因为每出来一个新状态,就把它赋值给相应的数组元素。所以,一个状态的父状态就可以指向父状态的数组下表index,到时候可以直接读取。还有一点需要注意的是进行hash时,不同的MAX取值可能会导致不同的结果,一般讲MAX取较大的素数,事实证明,用stl  <set>来存状态去重效率会低很多,用hash的话效率会高一些。对于路径的寻找,既然知道了每一状态的操作,则可以从目标状态开始将操作压栈,到时候出栈即为正确的从初始态到目标态的操作。

下面代码,进攻参考,欢迎批评指正

#include<stdio.h>#include<iostream>#include<string.h>#include<stdlib.h>#include<queue>#include<set>#include<stack>using namespace std;#define MAX 8000003struct node{char state[3][3];int parent;int x,y;char operation;}allstate[400000];int hash[MAX];//set<int> stateSet;queue<int> qu;stack<char>path;int dirx[4]={1,-1,0,0};int diry[4]={0,0,1,-1};int getHash(node n){int i,j,sum=0;for(i=0;i<3;i++)for(j=0;j<3;j++)sum=sum*10+n.state[i][j]-'0';return sum%MAX;}void getPath(node target){node temp=target;while(temp.parent!=-1){path.push(temp.operation);temp=allstate[temp.parent];}}void BFS(node head){memset(hash,0,sizeof(hash));int stateCount=0,i,hashValue;node outNode,newNode;bool isOk=false;hash[getHash(head)]=1;allstate[stateCount]=head;qu.push(stateCount);stateCount++;while(!qu.empty()){int index=qu.front();qu.pop();outNode=allstate[index];if(getHash(outNode)==3456735){isOk=true;break;}int x=allstate[index].x;int y=allstate[index].y;for(i=0;i<4;i++){int newx=x+dirx[i];int newy=y+diry[i];if(newx<0 || newx>2 || newy<0 || newy>2)continue;newNode=outNode;swap(newNode.state[x][y],newNode.state[newx][newy]);hashValue=getHash(newNode);if(hash[hashValue])continue;//stateSet.insert(hashValue);hash[hashValue]=1;newNode.x=newx;newNode.y=newy;newNode.parent=index;if(dirx[i]==0){if(diry[i]==1)newNode.operation='r';else newNode.operation='l';}if(diry[i]==0){if(dirx[i]==1)newNode.operation='d';else newNode.operation='u';}qu.push(stateCount);allstate[stateCount++]=newNode;}}if(!isOk){puts("unsolvable");return;}getPath(outNode);while(!path.empty()){cout<<path.top();path.pop();}cout<<endl;}int main(void){int i,j;node head;for(i=0;i<3;i++){for(j=0;j<3;j++){cin>>head.state[i][j];if(head.state[i][j]=='x'){head.state[i][j]='0';head.x=i;head.y=j;}}}head.parent=-1;head.operation='0';BFS(head);return 0;}