终于自己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 8000003
struct 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;
}