状态总数是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; }