走迷宮--圖的搜尋(bfs)並記錄路徑
阿新 • • 發佈:2019-02-12
題目描述:
一個網格迷宮由n行m列的單元格組成,每個單元格要麼是空地(用1表示),要麼是障礙物(用0來表示)。你的任務是找一條從起點到終點的最短步數和移動序列,其中UDLR表示上下左右操作。任何時候都不能在障礙物格子中,也不能走到迷宮之外。起點和終點保證都是空地。n,m<100。
樣例輸入:
6 5
11011
10111
10100
10111
11101
11111
樣例輸出:
9
DDDDDRRRR
解題思路:
較上一個文章來說,只是多了輸出路徑,這裡既然題目沒規定入口出口,為了方便起見,我人為的把入口和出口規定為左上角和右下角。記錄路徑即需要知道終點是由那個點走到的,而這個點的上一個點也需要知道……所以就記錄下每個點的父節點和相應的操作,然而準備輸出路徑的時候又遇到了一個問題:從出口一步步向上尋找,是一個倒著的,怎麼才能正著輸出呢?先進後出這個特點是棧對應的特點,而遞迴類似棧,所以利用遞迴的方式,達到按順序輸出的目的。
程式碼:
#include<cstdio> #include<queue> #include<iostream> using namespace std; char mmap[10][10]={}; int vis[10][10]={}; int n,m; int xx[4]={1,0,0,-1};//下、右、左、上 int yy[4]={0,1,-1,0}; struct node { int x,y; int t;//t表示走到這個格子用的步數 }; struct father { int x,y;//當前格子的父節點座標 char cz;//由什麼操作到達的這個格子 }; queue<node> q; node s,f; father lj[10][10];//記錄路徑 int bfs() { int i,j; s.x=0;s.y=0;s.t=0; f.x=n-1;f.y=m-1; q.push(s); lj[s.x][s.y].x=1000;//因為m,n<=100 lj[s.x][s.y].y=1000; lj[s.x][s.y].cz=0; vis[s.x][s.y]=1;//標為已經訪問過 while(!q.empty()) { node now=q.front(); q.pop(); for(i=0;i<4;++i) { node New; New.x=now.x+xx[i]; New.y=now.y+yy[i]; New.t=now.t+1; if(New.x<0||New.y<0||New.x>=n||New.y>=m||vis[New.x][New.y]||mmap[New.x][New.y]=='0')//下標越界或者訪問過或者是障礙物 continue; q.push(New); lj[New.x][New.y].x=now.x; lj[New.x][New.y].y=now.y; if(i==0) lj[New.x][New.y].cz='D'; else if(i==1) lj[New.x][New.y].cz='R'; else if(i==2) lj[New.x][New.y].cz='L'; else if(i==3) lj[New.x][New.y].cz='U'; vis[New.x][New.y]=1; if(New.x==f.x&&New.y==f.y) return New.t;//到達終點 } } return -1; } void dfs(int x, int y) { if(x==0&&y==0) return;//找到父節點是起點的格子了 else dfs(lj[x][y].x,lj[x][y].y); printf("%c",lj[x][y].cz); } int main() { int i,j,ans; scanf("%d%d",&n,&m); for(i=0;i<n;++i) { scanf("%s",mmap[i]); } ans=bfs(); if(ans<0) printf("error"); else { printf("%d\n",ans); dfs(n-1,m-1);//從終點開始找他的父節點 } return 0; }