zoukankan      html  css  js  c++  java
  • 走出迷宫、迷宫问题(思路讲解、模板)【深度优先搜索】

    走出迷宫

    题目链接(点击)

    当你站在一个迷宫里的时候,往往会被错综复杂的道路弄得失去方向感,如果你能得到迷宫地图,事情就会变得非常简单。

    假设你已经得到了一个n*m的迷宫的图纸,请你找出从起点到出口的最短路。

    输入

    第一行是两个整数n和m(1≤n,m≤100),表示迷宫的行数和列数。

    接下来n行,每行一个长为m的字符串,表示整个迷宫的布局。字符‘.’表示空地,‘#’表示墙,‘S’表示起点,‘T’表示出口。

    输出

    输出从起点到出口最少需要走的步数。

    样例输入

    3 3
    S#T
    .#.
    ...
    
    样例输出
    6

    思路:

    之前学长讲过bfs和dfs的知识,但是因为当时没做太多例题也没有太好的掌握这些知识,昨天看到迷宫这道题目就又看了看,但是不知道怎么下手,就又学了一下

    在矩阵中输入不同的字符要求从S出发到T 只能走 ‘ . ’ 问最少的步数

    深度优先搜索在这个题中相当于暴力每种可以走的路径 找到最短的一条路(通过递归实现)

    其好处就是:在走每种路径时可以记录所走的总步数 并且在终点处可以更新最少的步数然后输出

    AC代码:

    #include<stdio.h>
    const int MAX=1e5;
    int n,m,sum=MAX;
    int be1,be2,en1,en2;
    int dir[4][2]={0,1,0,-1,1,0,-1,0};
    char a[105][105];
    void dfs(int x,int y,int sum1)
    {
        if(x==en1&&y==en2){  //递归的最后终点 开始 return
            if(sum>sum1){   //加if 更新最小步数
                sum=sum1;
            }
            return;
        }
        for(int i=0;i<4;i++){
            x+=dir[i][0];  //借助方向数组dir改变x和y的值 实现走下一步
            y+=dir[i][1];
            if((a[x][y]=='.'||a[x][y]=='T')&&x>=0&&x<n&&y>=0&&y<m){ 
                a[x][y]='#';                  //x和y必须严格控制在矩阵内部
                dfs(x,y,sum1+1);
                a[x][y]='.';
            }
            x-=dir[i][0];  //实现返回
            y-=dir[i][1];
        }
    }
    int main()
    {
        scanf("%d%d",&n,&m);
        for(int i=0;i<n;i++){
            scanf("%s",a[i]);
        }
        for(int i=0;i<n;i++){
            for(int j=0;j<m;j++){
                if(a[i][j]=='S'){     // 要知道开始点和结束点的位置才能bfs
                    be1=i;
                    be2=j;
                }
                else if(a[i][j]=='T'){
                    en1=i;
                    en2=j;
                }
            }
        }
        bfs(be1,be2,0);  //sum1位置是从0开始
        printf("%d
    ",sum);
        return 0;
    }
    

    迷宫问题

    题目链接(点击)

    定义一个二维数组: 

    int maze[5][5] = {
    
    	0, 1, 0, 0, 0,
    
    	0, 1, 0, 1, 0,
    
    	0, 0, 0, 0, 0,
    
    	0, 1, 1, 1, 0,
    
    	0, 0, 0, 1, 0,
    
    };

    它表示一个迷宫,其中的1表示墙壁,0表示可以走的路,只能横着走或竖着走,不能斜着走,要求编程序找出从左上角到右下角的最短路线。

    Input

    一个5 × 5的二维数组,表示一个迷宫。数据保证有唯一解。

    Output

    左上角到右下角的最短路径,格式如样例所示。

    Sample Input

    0 1 0 0 0
    0 1 0 1 0
    0 0 0 0 0
    0 1 1 1 0
    0 0 0 1 0

    Sample Output

    (0, 0)
    (1, 0)
    (2, 0)
    (2, 1)
    (2, 2)
    (2, 3)
    (2, 4)
    (3, 4)
    (4, 4)

    思路:

    做了上面那个题又找了道新题试了试

    输出从左上角到右下角最短的路径

    区别是这道题不需要遍历找到开始和结束的点 但要输出路径 在递归暴力的时候可以看得出来 最终的路径并不是连续的 也就是说将每次递归x和y的值存起来然后输出是不太容易实现的 例如下面这个例子就特别麻烦

    想了好久 最后还是把x和y和sum1(到达每个点的最小步数)分别

    输出找到了方法:

    最终目标是4 4 点 从4 4 点开始往上找

    4 4 对应的sum1是7 则 下一步应该找6 让后是5…… 输出对应x和y就可以了

    AC代码:

    #include<stdio.h>
    const int MAX=1e6;
    int sum=MAX;
    int a[15][15];
    int dir[4][2]={0,1,0,-1,1,0,-1,0,};
    struct node{
        int num;
        int x;
        int y;
    }edge[MAX+5];
    struct node1{
        int x;
        int y;
    }edge1[MAX+5];
    int count=0;
    void dfs(int x,int y,int sum1)
    {
        if(x==4&&y==4){
            if(sum>sum1){
                sum=sum1;
            }
            return;
        }
        for(int i=0;i<4;i++){
            x+=dir[i][0];
            y+=dir[i][1];
            if(a[x][y]==0&&x>=0&&x<=4&&y>=0&&y<=4){
                a[x][y]=1;
                edge[count].num=sum1;
                edge[count].x=x;
                edge[count++].y=y;
                dfs(x,y,sum1+1);
                a[x][y]=0;
            }
            x-=dir[i][0];
            y-=dir[i][1];
        }
    }
    int main()
    {
        for(int i=0;i<5;i++){
            for(int j=0;j<5;j++){
                scanf("%d",&a[i][j]);
            }
        }
        dfs(0,0,0);          //下面的代码虽然看起来复杂但目的就是从后往前找sum1更小的值
        printf("(0, 0)
    ");
        int count1=0;
        for(int i=count-1;i>=0;i--){
            if(edge[i].x==4&&edge[i].y==4){
                int count2;
                for(int j=i;j>=0;j--){
                    if(edge[j].num<count2){
                        edge1[count1].x=edge[j].x;
                        edge1[count1++].y=edge[j].y;
                        count2=edge[j].num;
                    }
                }
                for(int j=count1-1;j>=0;j--){
                    printf("(%d, %d)
    ",edge1[j].x,edge1[j].y);
                }
                return 0;
            }
        }
        return 0;
    }
    
  • 相关阅读:
    把IDEA中新建的项目提交到Github仓库中
    在IDEA中设置方法自动注释(带参数和返回值)
    如何在 Maven 工程中引入其他jar包 并生效?(以 Netty 为例)
    在 IDEA 中 配置 Maven
    Visio中锁定元件
    DevExpress中 TreeList控件的常规配置
    从SuperSocket的App.config中读取配置,并修改保存,再重启服务
    devexpress 中 XtraTabcontrol 改变BackColor 的方法
    DevExpress 中 GridControl 的数据源DataTable 内容改变后 重新绑定
    如何在linux中设置tab键长度
  • 原文地址:https://www.cnblogs.com/ldu-xingjiahui/p/12407457.html
Copyright © 2011-2022 走看看