zoukankan      html  css  js  c++  java
  • 迷宫最短路径问题的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 
    ";
        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更加节省内存。

  • 相关阅读:
    iOS_文件上传进度条的实现思路-AFNettworking
    快手为什么成功
    Swift 3.1 的一些新特性
    字典类型的字符串转成字典
    phpmyadmin通过日志文件拿webshell
    计算机网络基础知识
    写一个php小脚本辅助渗透测试
    Zabbix exp编写
    sqlmap里如何添加字典
    过狗注入学习姿势分享2[投稿华盟网]
  • 原文地址:https://www.cnblogs.com/qingjiuling/p/9364633.html
Copyright © 2011-2022 走看看