1. 程式人生 > >紫書—八數碼問題(BFS)

紫書—八數碼問題(BFS)

sed 計算 cstring 藍橋杯 需要 amp 代碼 scan size

八數碼問題

編號為1~8的8個正方形滑塊被擺成3行3列(有一個格子空留),如圖所示。每次可以把與空格相鄰的滑塊(有公共邊才算相鄰)移到空格中,而它原來的位置就稱為了 新的空格。給定初始局面和目標局面(用0表示空格格),你的任務是計算出最少的移動步數。如果無法達到目標局面,則輸-1.

這是一道比較經典的BFS題目,有回溯的思想(不是廢話嗎)

還是有一些點需要註意的: 1.BFS較多使用隊列實現,因此在進行BFS時需要用到隊列(蒟蒻的筆者目前所了解orz)  那麽說到隊列,我就想到了孫悟空師徒四人一隊。。咳咳,說到隊列,就需要復習一下隊列了。  隊列有靜態以及STL實現,這題使用的是靜態,其實用STL也是可以的,只不過筆者對於STL的隊列操作不太熟練  因此這次使用的是靜態數組模擬隊列 2.對於在搜索過程中記錄中間狀態,紫書上介紹了3種方法:  ①運用編碼和解碼函數  ②哈希表  叁使用set STL  下面給出的代碼中有哈希的做法也有STL的做法,都是將0-8的位置轉換成9位int數進行存儲 3.memcpy和memcmp是<cstring>的對整塊內存的復制和比較函數,比循環比較和復制快(要學習一個) 4.每次進行一個節點進行搜索時,需要先復制隊頭的排列情況到隊尾,然後對隊尾進行操作,操作完成後隊尾向後移一位

技術分享圖片
 1 #include<cstdio>
 2 #include<set>
 3 #include<cstring>
 4 using namespace std;
 5 
 6 typedef int State[9];
 7 const int maxstate = 1000000;
 8 State st[maxstate],goal;
 9 int dist[maxstate];
10 int fa[maxstate];
11 
12 const int dx[]={-1,1,0,0};
13 const int dy[]={0
,0,-1,1}; 14 //使用set STL 15 set<int> vis; 16 void init_lookup_table(){vis.clear();} 17 int try_to_insert(int s){ 18 int v=0; 19 for(int i=0;i<9;i++) v=v*10+st[s][i]; 20 if(vis.count(v)) return 0; 21 vis.insert(v); 22 return 1; 23 } 24 25 //使用哈希 26 /*const int hashsize = 1000003;
27 int head[hashsize],Next[maxstate]; 28 void init_lookup_table(){memset(head,0,sizeof(head));} 29 30 int hash(State& s){ 31 int v=0; 32 for(int i=0;i<9;i++) v=v*10+s[i]; 33 return v % hashsize; 34 } 35 36 int try_to_insert(int s){ 37 int h = hash(st[s]); 38 int u = head[h]; 39 while(u){ 40 if(memcmp(st[u],st[s],sizeof(st[s]))==0) return 0; 41 u=Next[u]; 42 } 43 Next[s]=head[h]; 44 head[h]=s; 45 return 1; 46 }*/ 47 48 int bfs(){ 49 init_lookup_table(); 50 int front = 1,rear=2; 51 while(front<rear){ 52 State &s=st[front]; 53 if(memcmp(goal,s/*st[front]*/,sizeof(s))==0) return front; 54 int z; 55 for(z=0;z<9;z++) if(!s[z]) break; 56 int x=z/3,y=z%3; 57 for(int d=0;d<4;d++){ 58 int newx=x+dx[d]; 59 int newy=y+dy[d]; 60 int newz=newx*3+newy; 61 if(newx>=0 && newx<3 && newy>=0 && newy<3){ 62 State& t=st[rear]; 63 memcpy(&t,&s,sizeof(s)); 64 //memcpy(st[rear],st[front],sizeof(st[front])); 65 t[newz]=s[z]; 66 t[z]=s[newz]; 67 /*st[rear][newz]=st[front][z]; 68 st[rear][z]=st[front][newz];*/ 69 dist[rear] = dist[front]+1; 70 if(try_to_insert(rear)) rear++; 71 } 72 } 73 front++; 74 } 75 return 0; 76 } 77 78 int main(){ 79 for(int i=0;i<9; i++) scanf("%d",&st[1][i]); 80 for(int i=0;i<9; i++) scanf("%d",&goal[i]); 81 int ans=bfs(); 82 if(ans>0) printf("%d\n",dist[ans]); else printf("-1\n"); 83 return 0; 84 }
View Code

這道題還是很值得去琢磨的,裏面涉及了較多的內容,如set STL,哈希,encoding和decoding等等,也是細節滿滿的一道題。

話說我為什麽要在藍橋杯比賽前兩天突然發一篇題解呢?主要還是做題做累了(其實就是想偷懶),但又不能無所事事,就上來寫了一下題解qwq

最後還是希望藍橋杯rp++把

紫書—八數碼問題(BFS)