下面是八數位問題的一些演算法實現:
下面的代碼使用的是迭代加深的搜尋策略,由於這個演算法是dfs搜尋策略的改進,所以在dfs遞迴調用返回時,還是需要進行狀態還原的:
/*<br /> *迭代加深搜尋<br /> *<br />*/</p><p>#include<cstdio><br />#include<queue><br />#include<stack><br />#include<ctime><br />#include<cstring><br />using namespace std;</p><p>#define HashTableSize 362880<br />#define NOT !</p><p>typedef struct maps{<br />int detail[3][3];<br />int x,y;//記錄空格(0)的座標<br />}Map,*PMap;</p><p>Map org;//初始狀態<br />Map End;//目標狀態<br />bool HashTable[HashTableSize]={false};//hash表<br />const static int direction[4][2]={{-1,0},{1,0},{0,-1},{0,1}};//可移動的四個方向</p><p>int Path[100];<br />int Step;<br />int MaxDeep;<br />bool Finish;</p><p>/*<br /> *輸入八數位(在這裡不做有效性檢查)<br />*/<br />void input() {</p><p>int i,j;<br />int sum=0;</p><p>printf("輸入八數位序列:/n");<br />for(i=0;i<9;i++){</p><p>scanf("%d",*org.detail+i);//"."運算子的優先順序高於"*" </p><p>if( 0== *(*org.detail+i)){</p><p>org.x=i/3;<br />org.y=i%3;<br />}<br />}</p><p> for(i = 0 ; i < 9 ; i ++ ){ //計算順序數 </p><p> if( 0 == *(*org.detail + i) )<br /> continue; </p><p> for(j = 0 ; j < i; j ++ )<br /> if( 0 != *(*org.detail+j) && *(*org.detail + j) < *(*org.detail + i) )<br /> {<br /> sum ++;<br /> }<br /> } </p><p> if( sum%2 == 0 ) // 目標狀態各個數字對應的座標位置<br /> {<br /> End.detail[0][0] = 1 , End.detail[0][1] = 2 , End.detail[0][2] = 3 ;<br /> End.detail[1][0] = 4 , End.detail[1][1] = 5 , End.detail[1][2] = 6 ;<br /> End.detail[2][0] = 7 , End.detail[2][1] = 8 , End.detail[2][2] = 0 ;<br /> }<br /> else<br /> {<br /> End.detail[0][0] = 1 , End.detail[0][1] = 2 , End.detail[0][2] = 3 ;<br /> End.detail[1][0] = 8 , End.detail[1][1] = 0 , End.detail[1][2] = 4 ;<br /> End.detail[2][0] = 7 , End.detail[2][1] = 6 , End.detail[2][2] = 5 ;<br /> }<br /> return;<br />} </p><p>/*<br /> *檢測兩個狀態是否一樣<br />*/<br />inline bool IsEqual(Map a,Map b){</p><p>return 0==memcmp( (const void*)(*a.detail),(const void*)(*b.detail),36);<br />}</p><p>/*<br /> *hash值的計算<br />*/<br />int HashValue(Map a) {</p><p>int count;//記錄某個元素的逆序數<br />int i,j;</p><p>int value=0;<br />static int pv[9] ={1,1,2,6,24,120,720,5040,40320};<br />for(i=0;i<9;i++){<br />for(j=0,count=0;j<i;j++){<br />if(*(*a.detail+i)<*(*a.detail+j))//計算某個元素的逆序數<br />count++;<br />}<br />value+=pv[i]*count;<br />}<br />return value;<br />}</p><p>/*<br /> *深度優先搜尋的改進——迭代加深搜尋<br />*/<br />void Dfs(Map& node,int deep){</p><p>if(deep > MaxDeep)<br />return ;</p><p>if( true == IsEqual(node ,End) ){</p><p>Finish=true;<br />Step=deep;<br />return;<br />}</p><p>for(int k=0; k<4 && NOT Finish; k++){</p><p>Map tmp=node;<br />tmp.x=node.x+direction[k][0];<br />tmp.y=node.y+direction[k][1];</p><p>if( tmp.x<0 || tmp.x>2 || tmp.y <0 || tmp.y>2)<br />continue;</p><p>tmp.detail[node.x][node.y]=tmp.detail[tmp.x][tmp.y];<br />tmp.detail[tmp.x][tmp.y]=0;</p><p>int tmpindex=HashValue(tmp);<br />if( HashTable[tmpindex]==true)<br />continue;</p><p>HashTable[tmpindex]=true;<br />Path[deep]=k;//這裡通過記錄表示方向的k值來記錄路徑資訊<br />Dfs(tmp,deep+1);//使用遞迴的方法<br />HashTable[tmpindex]=false;<br />}<br />return;<br />}</p><p>/*<br /> *輸出結果<br />*/</p><p>void output(){</p><p>Map now=org;<br />int oldx,oldy,i,j;<br />int count=0;<br />printf("共需要%d./n",Step);<br />for(i=0;i<3;i++){<br />for(j=0; j<3;j++)<br />printf("%3d",org.detail[i][j]);<br />printf("/n");<br />}</p><p>for(int k=0; k<Step ;k++){</p><p>oldx=now.x;<br />oldy=now.y;<br />now.x+=direction[ Path[k] ][0];<br />now.y+=direction[ Path[k] ][1];</p><p>now.detail[oldx][oldy]=now.detail[now.x][now.y];//移動空格<br />now.detail[now.x][now.y]=0;</p><p>printf("/n 第%d步/n",++count);<br />getchar();</p><p>for(i=0;i<3;i++){<br />for(j=0;j<3;j++)<br />printf("%3d",now.detail[i][j]);<br />printf("/n");<br />}<br />}<br />printf("/n The End!/n");<br />return ;</p><p>}</p><p>int main(){</p><p>input();<br />clock_t time=clock();<br />HashTable[ HashValue(org) ] =true;</p><p>for( MaxDeep=1 ; 0 == Step;MaxDeep++){//迭代加深搜尋與Dfs的區別之處<br />Dfs(org,0);<br />}</p><p>printf("計算用時:%dMS/n",clock()-time);<br />output();<br />return 0;<br />}
上面解法的缺陷在於沒有考慮hash函數發生衝突的情況。