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更加节省内存。

  • 相关阅读:
    hdu 5646 DZY Loves Partition
    bzoj 1001 狼抓兔子 平面图最小割
    poj 1815 Friendship 最小割 拆点 输出字典序
    spoj 1693 Coconuts 最小割 二者取其一式
    hdu 5643 King's Game 约瑟夫环变形
    约瑟夫环问题
    hdu 5642 King's Order
    CodeForces 631C Report
    1039: C语言程序设计教程(第三版)课后习题9.4
    1043: C语言程序设计教程(第三版)课后习题10.1
  • 原文地址:https://www.cnblogs.com/qingjiuling/p/9364633.html
Copyright © 2011-2022 走看看