八数码算法研究

下面是八数码问题的一些算法实现:

 

下面的代码使用的是迭代加深的搜索策略,由于这个算法是dfs搜索策略的改进,所以在dfs递归调用返回时,还是需要进行状态还原的:

 

 

/* * 迭代加深搜索 * */ #include<cstdio> #include<queue> #include<stack> #include<ctime> #include<cstring> using namespace std; #define HashTableSize 362880 #define NOT ! typedef struct maps{ int detail[3][3]; int x,y; //记录空格(0)的坐标 }Map,*PMap; Map org; //初始状态 Map End; //目标状态 bool HashTable[HashTableSize]={false}; //hash表 const static int direction[4][2]={{-1,0},{1,0},{0,-1},{0,1}}; //可移动的四个方向 int Path[100]; int Step; int MaxDeep; bool Finish; /* * 输入八数码(在这里不做有效性检查) */ void input() { int i,j; int sum=0; printf("输入八数码序列:/n"); for(i=0;i<9;i++){ scanf("%d",*org.detail+i); //"."运算符的优先级高于"*" if( 0== *(*org.detail+i)){ org.x=i/3; org.y=i%3; } } for(i = 0 ; i < 9 ; i ++ ){ //计算顺序数 if( 0 == *(*org.detail + i) ) continue; for(j = 0 ; j < i; j ++ ) if( 0 != *(*org.detail+j) && *(*org.detail + j) < *(*org.detail + i) ) { sum ++; } } if( sum%2 == 0 ) // 目标状态各个数字对应的坐标位置 { End.detail[0][0] = 1 , End.detail[0][1] = 2 , End.detail[0][2] = 3 ; End.detail[1][0] = 4 , End.detail[1][1] = 5 , End.detail[1][2] = 6 ; End.detail[2][0] = 7 , End.detail[2][1] = 8 , End.detail[2][2] = 0 ; } else { End.detail[0][0] = 1 , End.detail[0][1] = 2 , End.detail[0][2] = 3 ; End.detail[1][0] = 8 , End.detail[1][1] = 0 , End.detail[1][2] = 4 ; End.detail[2][0] = 7 , End.detail[2][1] = 6 , End.detail[2][2] = 5 ; } return; } /* * 检测两个状态是否一样 */ inline bool IsEqual(Map a,Map b){ return 0==memcmp( (const void*)(*a.detail),(const void*)(*b.detail),36); } /* * hash值的计算 */ int HashValue(Map a) { int count; //记录某个元素的逆序数 int i,j; int value=0; static int pv[9] ={1,1,2,6,24,120,720,5040,40320}; for(i=0;i<9;i++){ for(j=0,count=0;j<i;j++){ if(*(*a.detail+i)<*(*a.detail+j)) //计算某个元素的逆序数 count++; } value+=pv[i]*count; } return value; } /* * 深度优先搜索的改进——迭代加深搜索 */ void Dfs(Map& node,int deep){ if(deep > MaxDeep) return ; if( true == IsEqual(node ,End) ){ Finish=true; Step=deep; return; } for(int k=0; k<4 && NOT Finish; k++){ Map tmp=node; tmp.x=node.x+direction[k][0]; tmp.y=node.y+direction[k][1]; if( tmp.x<0 || tmp.x>2 || tmp.y <0 || tmp.y>2) continue; tmp.detail[node.x][node.y]=tmp.detail[tmp.x][tmp.y]; tmp.detail[tmp.x][tmp.y]=0; int tmpindex=HashValue(tmp); if( HashTable[tmpindex]==true) continue; HashTable[tmpindex]=true; Path[deep]=k; //这里通过记录表示方向的k值来记录路径信息 Dfs(tmp,deep+1); //使用递归的方法 HashTable[tmpindex]=false; } return; } /* * 输出结果 */ void output(){ Map now=org; int oldx,oldy,i,j; int count=0; printf("共需要%d./n",Step); for(i=0;i<3;i++){ for(j=0; j<3;j++) printf("%3d",org.detail[i][j]); printf("/n"); } for(int k=0; k<Step ;k++){ oldx=now.x; oldy=now.y; now.x+=direction[ Path[k] ][0]; now.y+=direction[ Path[k] ][1]; now.detail[oldx][oldy]=now.detail[now.x][now.y]; //移动空格 now.detail[now.x][now.y]=0; printf("/n 第%d步/n",++count); getchar(); for(i=0;i<3;i++){ for(j=0;j<3;j++) printf("%3d",now.detail[i][j]); printf("/n"); } } printf("/n The End!/n"); return ; } int main(){ input(); clock_t time=clock(); HashTable[ HashValue(org) ] =true; for( MaxDeep=1 ; 0 == Step; MaxDeep++){ //迭代加深搜索与Dfs的区别之处 Dfs(org,0); } printf("计算用时:%dMS/n",clock()-time); output(); return 0; }

 

上面解法的缺陷在于没有考虑hash函数发生冲突的情况。

 

 

你可能感兴趣的:(八数码算法研究)