【DFS/BFS】NYOJ-58-最少步數(迷宮最短路徑問題)


【題目鏈接:NYOJ-58

  經典的搜索問題,想必這題用廣搜的會比較多,所以我首先使的也是廣搜,但其實深搜同樣也是可以的。

  不考慮剪枝的話,兩種方法實踐消耗相同,但是深搜相比廣搜內存低一點。

  我想,因為廣搜需要的就是隊列,所以相比遞歸隊列更耗內存?

  當然DFS並不像上圖所說,需要用棧,而是運用遞歸即可。

 

BFS:

  

  因為BFS是要一個接一個的遍歷,所以用到了結構體,來保存坐標和當前所走步數

  1.每走一步,通過定義的結構體,從隊列中提取a(即上一步的坐標、步數(步數每次累加)

  2.在a的基礎上進行對a周圍四個方向進行判斷,找出可以繼續走的位置(即非障礙、邊界),並將該位置的坐標,進入隊列中

  繼續走下一步時,循環以上1.2兩步操作

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cstring>
 4 #include<algorithm>
 5 #include<queue>
 6 using namespace std;
 7 int dir[4][2]= {1,0,-1,0,0,1,0,-1};
 8 struct point{
 9     int x,y,step;
10 };
11 int bfs(point s,point e,int map[9][9]){
12     queue<point>tp;//自定義類型的隊列 
13     int i;
14     point t;//保存當前坐標 ,臨時變量 
15     //s表示之前
16     //e表示目標 
17     s.step=0;//保存步數 
18     map[s.x][s.y]=1;//標記此處已經走過 
19     tp.push(s);//初始化隊列 ,s中(x,y)初始為起始坐標,step = 0 
20     while(!tp.empty()){//循環直至隊列為空 
21         s=tp.front();//每次循環s都等於隊首 
22         tp.pop();//刪除隊首 
23         if(s.x==e.x&&s.y==e.y)//如果當前坐標與目標坐標相等
24             return s.step;    //返回當前的步數 
25         //遍歷四個不同的方向 
26         //如果是通道(0),即增加步數 
27         for(int i=0; i<4; i++){
28             t.x=s.x+dir[i][0];
29             t.y=s.y+dir[i][1];
30             if(map[t.x][t.y]==0){//如果是通道 
31                 t.step=s.step+1;
32                 map[t.x][t.y]=1;//標記此處已經走過,及標記為牆 
33                 tp.push(t);
34             }
35         }
36     }
37 }
38 int main(){
39     int t;
40     scanf("%d",&t);
41     while(t--){
42         point s,e;
43         int map[9][9]= {1,1,1,1,1,1,1,1,1,
44                         1,0,0,1,0,0,1,0,1,
45                         1,0,0,1,1,0,0,0,1,
46                         1,0,1,0,1,1,0,1,1,
47                         1,0,0,0,0,1,0,0,1,
48                         1,1,0,1,0,1,0,0,1,
49                         1,1,0,1,0,1,0,0,1,
50                         1,1,0,1,0,0,0,0,1,
51                         1,1,1,1,1,1,1,1,1,};
52         scanf("%d%d%d%d",&s.x,&s.y,&e.x,&e.y);
53         printf("%d\n",bfs(s,e,map));
54     }
55     return 0; 
56 }

 

DFS:

  DFS就沒什么好說了,不明白可以看看之前的DFS博客

  只不過這里,沒有用到單獨的二維數組see[][],來判斷本個坐標是已經搜索過

  而是結合題意,把當前所在位置變為'1',即障礙、邊界,那么在遞歸往下延伸判斷四周時,達到同樣的目的

  當然在DFS函數最后,需要把Map[][]重新變為'0',因為遞歸執行的順序是自上而下再從下向上返回

  因為是多組測試數據,所以需要在遞歸返回時,把迷宮“恢復原貌”

#include<iostream>
using namespace std;
#define min(a,b) a < b ? a : b
int Map[9][9] = {1,1,1,1,1,1,1,1,1,
                    1,0,0,1,0,0,1,0,1,
                    1,0,0,1,1,0,0,0,1,
                    1,0,1,0,1,1,0,1,1,
                    1,0,0,0,0,1,0,0,1,
                    1,1,0,1,0,1,0,0,1,
                    1,1,0,1,0,1,0,0,1,
                    1,1,0,1,0,0,0,0,1,
                    1,1,1,1,1,1,1,1,1,};
int a,b,c,d,num;                    
void dfs(int x,int y,int s){
    if(Map[x][y]) return;
    if(x == c && y == d){
        num = min(s,num);
        return;
    }
    s++;
    Map[x][y] = 1;
    dfs(x - 1,y,s);
    dfs(x + 1,y,s);
    dfs(x,y - 1,s);
    dfs(x,y + 1,s);
    Map[x][y] = 0;    
}
int main(){
    int n;
    cin >> n;
    while(n--){
        num = 10000;
        cin >> a >> b >> c >> d;
        dfs(a,b,0);
        cout << num << endl;
    }    
    return 0;
}

 

DFS,BFS講解PPT:click here || there

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM