迷宮最短路徑問題的dfs,bfs實現


                  迷宮的最短路徑
給定一個大小為 N×M的迷宮。迷宮由通道和牆壁組成,每一步可以向鄰接的上下左右四格的通道移動。請求出從起點到終點所需的小步數。請注意,本題假定從起點一定可以移動到終點

限制條件:N,M<=100;

樣例輸入:N=10,M=10('#','.','S','G'分別表示牆壁,通道,起點和終點)

#S######.#

......#..#

.#.##.##.#

.#........

##.##.####

....#....#

.#######.#

....#.....

.####.###.

....#...G#  

dfs分析:主要考慮當前應該怎么做,每到一個點下一步有上下左右四種情況,我們按順時針方向右下左上來進行計算,到新的一個點判斷是否走過以及有沒有障礙物,如果答案是確定的就可以繼續dfs。 

#include <iostream>
#include <cstdio>
using namespace std;
int p0,q0,p1,q1;//儲存起始點和終點的橫縱坐標
char a[100][100];//根據數據量自己調整 
int book[100][100];//標記數組來判斷有沒有到達 
int next[4][2]={{0,1},{1,0},{0,-1},{-1,0}};//分別儲存x,y坐標下一步的可能情況 
int mini=99999;//先給最小路徑一個很大的初值     
int n,m;
void dfs(int x,int y,int step){
    if(x==p1&&y==q1){
        if(step<mini)
        mini=step; 
        return ;//函數直接結束
    }
    for(int k=0;k<4;k++){
        int nx=x+next[k][0], ny=y+next[k][1];//枚舉下一步可能的橫縱坐標
        if(nx<1||nx>n||ny<1||ny>m){//控制不越界 
            continue;
        }
        if(book[nx][ny]==0&&a[nx][ny]=='.'||book[nx][ny]==0&&a[nx][ny]=='G'){
            //cout<<step<<endl;
            book[nx][ny]=1;//標記走過了 
            dfs(nx,ny,step+1);
            book[nx][ny]=0;//注意dfs后返回這一點為沒走過。 
        }
    } 
        return ; 
}
int main(){
    cin>>n>>m;
    for(int i=1;i<=n;i++){
        for(int j=1;j<=m;j++){
            cin>>a[i][j];
            if(a[i][j]=='S'){
                p0=i;q0=j;
            }
            if(a[i][j]=='G'){
                p1=i;q1=j;
            }
        }
    }
    //cout<<p0<<q0<<p1<<q1<<endl;
    //if(a[2][1]=='.')    cout<<"just a test \n";
    book[p0][q0]=1;//標記起始點走過了 
    dfs(p0,q0,0);
    cout<<mini<<endl;
    return 0;
}

 

BFS分析:同深搜選擇一個點之后不斷繼續往下深入不同,寬搜是記錄所有到達后步數相同的點,更適宜做最短路徑的問題。

#include <iostream>
#include <cstdio>
using namespace std;
char a[100][100];//根據題意自己設定數據量 
int book[100][100];//標記某點是否到達 
int sx,sy,gx,gy;//起始點坐標 
struct node{
    int x;
    int y;
    int s;//s表示步數 
};
node q[10000];//100*100的地圖隊列擴展最多是10000 
int main(){
int head,tail;head=tail=1; //一開始清空隊列     
    int n,m;
    cin>>n>>m;
    for(int i=1;i<=n;i++){
        for(int j=1;j<=m;j++){
            cin>>a[i][j];
            if(a[i][j]=='S'){
                sx=i;sy=j;
            }
            if(a[i][j]=='G'){
                gx=i;gy=j;
            }
        }
    }
    int next[4][2]={{1,0},{0,1},{-1,0},{0,-1}};
    q[tail].x=sx;q[tail].y=sy;q[tail].s=0;//將起點數據壓入隊列
    tail++; book[sx][sy]=1;
    int flag=0;//flag是為了找到最短路徑后跳出while循環用的 
    while(head<tail){
        for(int k=0;k<4;k++){
            int tx=q[head].x+next[k][0],ty=q[head].y+next[k][1];
            //判斷是否越界
            if(tx<1||tx>n||ty<1||ty>m)
            continue;
            if(book[tx][ty]==0&&a[tx][ty]!='#'){
                q[tail].x=tx;q[tail].y=ty;q[tail].s=q[head].s+1;
                book[tx][ty]=1;tail++;
            }
            if(tx==gx&&ty==gy){
                flag=1;
                break;
            } 
        }
        if(flag)    break;
        head++;
    }
    cout<<q[tail-1].s<<endl;
    return 0;
}

總結一下,dfs和bfs都能都能生成所有能夠遍歷到的狀態,但是遞歸可以更尖端的編寫且管理起來更簡單,所以大多數情況還是用dfs實現,反之,bfs處理起最短路徑時更方便。

此外,dfs更加節省內存。


免責聲明!

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



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