主要使用了A*搜索和hash函数
#include<iostream>
#include<stdlib.h>using namespace std;
typedef struct Direction{
char pre;//前一节点到后一节点的移动方向
Direction *prior;
}Direction;
typedef struct State{
int no[9];//数字序列
int space;//空格位置
int steps;//到达该状态是已走过的步数
int f;//估价函数值
State *next;
Direction *dir;
}State;
bool flag[700000];//节点hash表,每一个节点的状态,true 表示该节点已遍历
int dest[]={8,0,1,2,3,4,5,6,7};//dest[i]表示数字i的目标位置
int fac[10];//阶乘序列
char direct[4]={'u','d','l','r'};
int expect(int *no)//启发函数
{
int h=0;
for(int i=0;i<9;++i)
h+=abs(i/3-dest[no[i]]/3)+abs(i%3-dest[no[i]]%3);
return h;
}
int hash(int *no)//hash函数
{
int h=0;
for(int i=8;i>=0;--i)
{
int count=0;
for(int j=8;j>i;--j)
if(no[j]<no[i])
count++;
h+= count*fac[8-i];
}
return h;
}
void print(Direction *dir)//输出方向,逆向输出
{
if(dir->prior)
print(dir->prior);
cout<<dir->pre;
}
bool produce(State *res,State *&des,int i)//生成新节点,i表示方向
{
int row=res->space/3;
int col=res->space%3;
int row_n,col_n;
switch(i)
{
case 0:
if(row<=0) return false;
row_n=row-1;
col_n=col;
break;
case 1:
if(row>=2) return false;
row_n=row+1;
col_n=col;
break;
case 2:
if(col<=0) return false;
row_n=row;
col_n=col-1;
break;
case 3:
if(col>=2) return false;
row_n=row;
col_n=col+1;
break;
default:return false;
}
des=(State *)malloc(sizeof(State));
for(int j=0;j<9;++j)
des->no[j]=res->no[j];
des->no[row*3+col]=des->no[row_n*3+col_n];
des->no[row_n*3+col_n]=0;
des->space=row_n*3+col_n;
des->steps=res->steps+1;
des->f=des->steps+expect(des->no);
des->dir=(Direction *)malloc(sizeof(Direction));
des->dir->pre=direct[i];
des->dir->prior=res->dir;
return true;
}
int main()
{
fac[0]=1;
char ch;
for(int i=1;i<10;++i)
fac[i]=fac[i-1]*i;
State *start=(State *)malloc(sizeof(State));
State *open=(State *)malloc(sizeof(State));//用于存放新生成的节点
for(int i=0;i<9;++i)
{
cin>>ch;
if(ch=='x')
{
start->no[i]=0;
start->space = i;
}
else start->no[i]=(int )(ch-'0');
}
start->steps=0;
start->f=start->steps+expect(start->no);
start->next=NULL;
start->dir=NULL;
open->next=start;
//对flag表进行初始化
for(int i=0;i<fac[9];++i)
flag[i]=false;
while(open->next)
{
State *op=open->next;//当前待操作节点
if(op->f==op->steps)
{
print(op->dir);
cout<<endl;
getchar();
return 0;
}
//生成新节点 0123分别对应于上下左右
open->next=op->next;
for(int i=0;i<4;++i)
{
State *node;
if(produce(op,node,i)&&!flag[hash(node->no)])
{
State *temp_node=open;
while(temp_node->next && (temp_node->next->f < node->f))//将新节点按估价值顺序插入open
temp_node=temp_node->next;
node->next=temp_node->next;
temp_node->next=node;
}
}
flag[hash(op->no)]=true;
free(op);
}
cout<<"unsolvable"<<endl;
}