http://hi.baidu.com/wangz_j/blog/item/8dad3fcfbf31e41593457e51.html
IDA*即迭代加深的A*搜索,实现代码是最简练的,无须状态判重,无需估价排序。那么就用不到哈希表,堆上也不必应用,空间需求变的超级少。效率上,应用了曼哈顿距离。同时可以根据深度和h值,在找最优解的时候,对超过目前最优解的地方进行剪枝,这可以导致搜索深度的急剧减少,所以,这是一个致命的剪枝!因此,IDA*大部分时候比A*还要快,可以说是A*的一个优化版本!
代码:
#include <iostream> #include <cmath> #include <cstdlib> #include <cstdio> #include <cstring> 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 arr[3][3]; int r,c; }STATUS; char dirCode[] = {"dulr"}; char rDirCode[] = {"udrl"}; char path[M]; // 最优解 STATUS begin, end = { 1,2,3,4,5,6,7,8,0,2,2 }; // 起始和终止状态 int maxDepth = 0; // 深度边界 int diff(const STATUS &cur) // 启发函数 { int i,j,k,m,ans=0; for(i=0;i<=2;i++) for(j=0;j<=2;j++) { if(cur.arr[i][j] != 0) { for(k=0;k<=2;k++) for(m=0;m<=2;m++) { if(cur.arr[i][j] == end.arr[k][m]) { ans+=abs(i-k)+abs(j-m); break; } } } } return ans; } bool dfs(STATUS &cur, int depth, int h, char preDir) { if(memcmp(&cur, &end, sizeof(STATUS)) == 0 ) { // OK找到解了:) path[depth] = '/0'; return true; } if( depth + h > maxDepth ) return false; // 剪枝 STATUS nxt; // 下一状态 for(int i=0; i<4; i++) { if(dirCode[i]==preDir) continue; // 回到上次状态,剪枝 nxt = cur; nxt.r = cur.r + dir[i][0]; nxt.c = cur.c + dir[i][1]; if( !( nxt.r >= 0 && nxt.r < 3 && nxt.c >= 0 && nxt.c < 3 ) ) continue; int nxth = h; int preLen,Len,desNum=cur.arr[nxt.r][nxt.c],desR=(desNum-1)/3,desC=(desNum-1)%3; preLen=abs(nxt.r-desR)+abs(nxt.c-desC); Len=abs(cur.r-desR)+abs(cur.c-desC); nxth = h - preLen + Len; swap(nxt.arr[cur.r][cur.c], nxt.arr[nxt.r][nxt.c]); path[depth] = dirCode[i]; if(dfs(nxt, depth + 1, nxth, rDirCode[i])) return true; } return false; } int IDAstar() { int nh = diff(begin); maxDepth = nh; while (!dfs(begin, 0, nh, '/0')) maxDepth++; return maxDepth; } void Input() { char ch; int i, j; for(i=0; i < 3; i++){ for(j=0; j < 3; j++){ do{ scanf("%c", &ch); } while( !( ( ch >= '1' && ch <= '8' ) || ( ch == 'x' ) ) ) ; if( ch == 'x' ) { begin.arr[i][j] = 0; begin.r = i; begin.c = j; } else begin.arr[i][j] = ch - '0'; } } } bool IsSolvable(const STATUS &cur) { int i, j, k=0, s = 0; int a[8]; for(i=0; i < 3; i++){ for(j=0; j < 3; j++){ if(cur.arr[i][j]==0) continue; a[k++] = cur.arr[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); } int main() { Input(); if(IsSolvable(begin)){ IDAstar(); printf("%s/n", path); } else printf("unsolvable/n"); return 0; }