【C++演算法設計】八數碼問題
阿新 • • 發佈:2019-02-05
八數碼問題
【題意】
編好為1~8的8個正方形滑塊擺成3行3列(一個格子為空),如圖所示每次可以移動空格相鄰的滑塊到空格,要計算出能移動出目標局面的最小步數,如無法達到則輸出-1。
【分析】
我們可以把每一種局面定義為一種“狀態”,而每個狀態就是由9個格子的編號依次排列組成,如上圖左的狀態為:1,5,2,4,3,0,7,8,6,同理右的狀態為:1,2,3,4,5,6,7,8,0。然後我們可以用寬度優先遍歷搜尋(BFS)的方法,對每一種狀態都進行擴展出新的狀態,然後知道搜尋出目標狀態為止。【程式碼】
typedef int State[9]; //定義“狀態”型別 const int Maxstate = 1000000; State st[Maxstate],goal; //狀態陣列 int dist[Maxstate]; //如果要列印方案,還要定義一個父親編號陣列 int fa[Maxstate]; const int dx[]={-1,1,0,0}; const int dy[]={0,0,-1,1}; void init(){} //初始化函式 int bfs() { init(); int front=1; int rear=2; while(front<rear) { State& s = st[front]; if(memcmp(goal,s,sizeof(s))==0) return front; int z; for(z=0;z<9;z++) if(!s[z]) break; int x=z/3,y=z%3; for (int d=0;d<4;d++) { int newx=x+dx[d]; int newy=y+dy[d]; int newz=newx*3+newy; if(newx>=0 && newx<3 && newy>=0 &&newy<3) { State& t=st[rear]; memcpy(&t,&s,sizeof(s)); t[newz]=s[z]; t[z]=s[newz]; dist[rear]=dist[front]+1; if(insert(rear)) rear++; //判重 } } front++; } return 0; }
上面這段程式碼缺少一個main()函式,一個init()函式和一個判重的insert()函式,我覺著比較重要的一個點時定義“狀態”型別的寫法,我開始覺著應該是typedef int[9] State這麼寫的,但是不對,具體為什麼要那麼寫我也不清楚,反正很容易寫錯。然後就是最關鍵的bfs函式中用了很多“引用”,這可以學習一下,這樣做很方便,比指標好理解。