状态总数是9! = 362880 种,不算太多,可以满足广搜和A*对于空间的需求。
假如把x看做0。最大为876543210没超过Int的存储范围,所以用一个int值来表示其平面状态。
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <queue>
#include <vector>
#define keyMax 999983
#define target 123456780
using namespace std;
struct node1{
int val;//此状态的Int表示
char step;//从上一个状态转移到这个状态做的操作
int pre_num;//前一个状态在状态表中的编号
int count_step;//从起点到这个状态的实际代价
};
struct node2{
int evaluate;//评估代价
int num;//这个状态对应的状态表中的编号
bool operator < (const node2 &a) const {
return evaluate>a.evaluate;
}
};
int hashTable[keyMax];//哈希表记录状态是否遍历过
char direction[4]={'u','d','l','r'};
int exchange[9][4]={//exchange[i][j]表示x在位置i 做direction[j]操作 该到哪个位置
{-1,3,-1,1},
{-1,4,0,2},
{-1,5,1,-1},
{0,6,-1,4},
{1,7,3,5},
{2,8,4,-1},
{3,-1,-1,7},
{4,-1,6,8},
{5,-1,7,-1}
};
int move[9][9]={ move[i][j] 表示 位置i移动到位置j需要几步
{0,1,2,1,2,3,2,3,4},
{1,0,1,2,1,2,3,2,3},
{2,1,0,3,2,1,4,3,2},
{1,2,3,0,1,2,1,2,3},
{2,1,2,1,0,1,2,1,2},
{3,2,1,2,1,0,3,2,1},
{2,3,4,1,2,3,0,1,2},
{3,2,3,2,1,2,1,0,1},
{4,3,2,3,2,1,2,1,0}
};
vector<node1> state_table;//状态表
priority_queue<node2> que;//优先队列
void init()
{//初始化哈希表、将优先队列、状态表清空
memset(hashTable,0,sizeof(hashTable));
state_table.clear();
while(!que.empty())
que.pop();
}
int getValue(char *s)
{//将输入内容转换成int值表示
int i;
int res=0;
int len=strlen(s);
for(int i=0;i<len;i++)
{
if(s[i]<='9'&&s[i]>='1')
res=res*10+s[i]-'0';
else if(s[i]=='x')
res*=10;
}
return res;
}
int getKey(int val)
{
return val%keyMax;
}
void addInHashTalbe(int val)
{
int key=getKey(val);
while(hashTable[key])
{
++key;
if(key==keyMax)
key=0;
}
hashTable[key]=val;
}
bool isInHashTable(int val)
{
int key=getKey(val);
while(true)
{
if(!hashTable[key])
return false;
if(hashTable[key]==val)
return true;
++key;
if(key==keyMax)
key=0;
}
}
int evaluation(int val)
{//评估函数 为每个数从状态中的位置直接到自己该到的位置的步数之和
int res=0;
for(int i=8;i>=0;i--)
{
int num=val%10-1;
if(num==-1)
continue;
res+=move[i][num];
val/=10;
}
return res;
}
void print_answer(int num)
{
int pre=state_table[num].pre_num;
if(pre==-1)
return;
print_answer(pre);
printf("%c",state_table[num].step);
}
bool a_star(int val)
{
addInHashTalbe(val);
state_table.push_back((node1){val,'s',-1,0});
que.push((node2){evaluation(val),state_table.size()-1});
while(!que.empty())
{
node2 this_state=que.top();que.pop();
if(state_table[this_state.num].val==target)
{
print_answer(this_state.num);
return true;
}
int i;
int t=state_table[this_state.num].val,loc;
int v[9];
for(i=8;i>=0;i--)
{
if(t%10==0)
loc=i;
v[i]=t%10;
t/=10;
}
for(i=0;i<4;i++)
{
if(exchange[loc][i]==-1)//不能转移的方向标记为-1
continue;
t=0;
for(int j=0;j<=8;j++)
{
if(j==loc)
t=t*10+v[exchange[loc][i]];
else if(j==exchange[loc][i])
t=t*10+v[loc];
else t=t*10+v[j];
}
if(!isInHashTable(t))
{
addInHashTalbe(t);
state_table.push_back((node1){t,direction[i],this_state.num,state_table[this_state.num].count_step+1});
que.push((node2){state_table[this_state.num].count_step+1+evaluation(t),state_table.size()-1});
}
}
}
return false;
}
int main()
{
char ch[50];
while(gets(ch)!=NULL)
{
init();
int val=getValue(ch);
if(!a_star(val))
printf("unsolvable");
printf("\n");
}
return 0;
}