该文主要介绍用IDA*算法实现八数码问题
IDA*算法即迭代加深的A*算法,实现代码是最简练的,无须状态判重,无需估价排序
IDA*大部分时候比A*还要快,可以说是A*的一个优化版本!
/* POJ 1077 Eight C++ Memory 168K Time 32MS */ #include <iostream> #include <string> using namespace std; const unsigned int M = 1001; int dir[4][2] = { 1, 0, // Down -1, 0, // Up 0,-1, // Left 0, 1 // Right }; typedef struct STATUS{ int data[3][3]; int r,c;//0所在的位置 }STATUS; char dirCode[] = {"dulr"}; char rDirCode[] = {"udrl"}; char path[M]; // 最优解 STATUS start, goal = { 1,2,3,4,5,6,7,8,0,2,2 }; // 起始和终止状态 int maxDepth = 0; // 深度边界 //计算h值,作为IDAstar算法的评估函数 int dist(STATUS suc, STATUS goal, int k) {//计算方格的错位距离 int si,sj,gi,gj; //si,sj表示suc中k所处位置,gi,gj表示goal中k所处的位置 for(int i=0;i<3;i++) for(int j=0;j<3;j++){ if(suc.data[i][j]==k){ si=i;sj=j; } if(goal.data[i][j]==k){ gi=i; gj=j; } } return abs(si-gi) + abs(sj-gj); } int H(STATUS suc, STATUS goal) {//计算 h 值 int h = 0; for(int i = 1; i <= 8; i++) h = h + dist(suc, goal, i); return h; } //计算h值结束 //IDAstar算法开始 bool dfs(STATUS cur,int depth,int h,char preDir){ //IDA*估值函数剪枝 //当前局面的估价函数值+当前的搜索深度 > 预定义的最大搜索深度时剪枝 if(depth+h>maxDepth)return false; if(memcmp(&cur, &goal, sizeof(STATUS)) == 0 ) { path[depth] = ‘\0‘; return true; } STATUS next; for(int i=0;i<4;++i){ if(dirCode[i]==preDir)continue;//不能回到上一状态 next=cur; next.r = cur.r + dir[i][0]; next.c = cur.c + dir[i][1]; if( !( next.r >= 0 && next.r < 3 && next.c >= 0 && next.c < 3 ) ) continue; swap(next.data[cur.r][cur.c], next.data[next.r][next.c]); //置换变成新的状态 int nexth=H(next,goal);//重新计算h值 path[depth] = dirCode[i]; if(dfs(next, depth + 1, nexth, rDirCode[i])) return true; } return false; } int IDAstar(){ int h = H(start,goal); maxDepth = h; while (!dfs(start,0, h, ‘\0‘)) maxDepth++; return maxDepth; } //IDAstar算法结束 //是否可解 bool IsSolvable(const STATUS &cur) { int i, j, k=0, s = 0; int a[9]; for(i=0; i < 3; i++){ for(j=0; j < 3; j++){ if(cur.data[i][j]==0) continue; a[k++] = cur.data[i][j]; } } for(i=0; i < 8; i++){ for(j=i+1; j < 8; j++){ if(a[j] < a[i]) s++; } } return (s%2 == 0); } //初始状态赋值 void input(){ char c; for(int i=0;i<3;i++){ for(int j=0;j<3;j++){ cin>>c; if(c==‘x‘){start.data[i][j]=0;start.r=i;start.c=j;} else start.data[i][j]=c-‘0‘; } } } int main(){ freopen("C:\\in.txt","r",stdin); input(); if(IsSolvable(start)){ IDAstar(); cout<<path<<endl; } else cout<<"unsolvable"<<endl; return 0; }