IDA*比较好,重复路径也无所谓了,A*存状态判重意义不大,不实用
IDA*就是限制搜索深度的dfs,多加了一个limit限制条件,可以得到最优解
八数码的一些解释http://wenku.baidu.com/view/37a1b7a4284ac850ad024269.html
别人的总结http://www.cnblogs.com/JMDWQ/category/383627.html
这篇写的挺简明http://blog.csdn.net/ysjjovo/article/details/6657008
#include<stdio.h>//2 3 4 1 5 x 7 6 8 #include<string.h> #include<math.h> #define size 3 int move[4][2]={{-1,0},{0,-1},{0,1},{1,0}};//上 左 右 下 char op[4]={'u','l','r','d'}; int map[size][size],map2[size*size],limit,path[100]; int flag,length; //int goal_st[3][3]={{1,2,3},{4,5,6},{7,8,0}}; int goal[9][2]={{2,2},{0,0},{0,1},{0,2},{1,0},{1,1},{1,2},{2,0},{2,1}};//目标位置 int nixu(int a[size*size])//算逆序数,逆序数为偶数状态可达 { int i,j,ni; ni=0; for(i=0;i<size*size;i++) { if(a[i]==0) //空格不算,只算八个数块的逆序 continue; for(j=i+1;j<size*size;j++) { if(a[j]==0) continue; if(a[i]>a[j]) ni++; } } if(ni%2==0) return 1; else return 0; } int hv(int a[][size])//估价函数,曼哈顿距离,小等于实际总步数 { int i,j,cost=0; for(i=0;i<size;i++) { for(j=0;j<size;j++) { int w=map[i][j]; cost+=abs(i-goal[w][0])+abs(j-goal[w][1]); } } return cost; } void swap(int*a,int*b) { int tmp; tmp=*a; *a=*b; *b=tmp; } void dfs(int sx,int sy,int len,int pre_move)//sx,sy是空格的位置 { int i,j,nx,ny; if(flag) return; int dv=hv(map); if(len==limit) { if(dv==0) { flag=1; length=len; return; } else return; } else if(len<limit) { if(dv==0) { flag=1; length=len; return; } } for(i=0;i<4;i++) { if(i+pre_move==3&&len>0)//不和上一次移动方向相反,对第二步以后而言 continue; nx=sx+move[i][0]; ny=sy+move[i][1]; if(0<=nx&&nx<3 && 0<=ny&&ny<3) { swap(&map[sx][sy],&map[nx][ny]); int p=hv(map); if(p+len<=limit&&!flag) { path[len]=i; dfs(nx,ny,len+1,i); if(flag) return; } swap(&map[sx][sy],&map[nx][ny]); } } } int main() { int i,j,k,l,m,n,sx,sy; char c,g; flag=0; memset(path,-1,sizeof(path)); i=0; while(i<9) { scanf("%c",&c); if(c==32) continue; if(c=='x') { map2[i]=0; map[i/3][i%3]=0; sx=i/3;sy=i%3; i++; } else { map2[i]=c-48; map[i/3][i%3]=c-48; i++; } } if(nixu(map2)==1)//该状态可达 { limit=hv(map); limit=0; while(!flag)//找不到就加大limit,只要状态可达,就总会找到路径,每次搜索的深度都不大于limit,虽然可能错过正确解,但减少了错误路径的搜索长度,总的来说节省了时间 { dfs(sx,sy,0,0); if(!flag) limit++; //得到的是最小步数 } for(i=0;i<length;i++) printf("%c",op[path[i]]); printf("\n"); } else printf("unsolvable\n"); return 0; }16MS