BFS-走迷宫问题【Munching-OJ1381】

参考博客

https://www.cnblogs.com/handsomecui/p/4946151.html

https://www.cnblogs.com/pealicx/p/6115669.html
https://blog.csdn.net/c_uizrp_dzjopkl/article/details/82287505

 

题目描述

Bessie loves her grass and loves to hurry to the barn for her evening milking session. She has partitioned the pasture into a rectilinear grid of R (1 <= R <= 100) rows and C (1 <= C <= 100) columns and marked the squares as grass or rocky (she can't eat rocks and won't even go into those squares). Bessie starts on her map at location R_b,C_b and wishes to munch her way, square by square, to the barn at location 1,1 by the shortest route possible. She moves from one square to any one of the potentially four adjacent squares. Below is the original map [with rocks ('*'), grass ('.'), the barn ('B'), and Bessie ('C' for cow) at row 5, col 6] and a route map with the optimal route marked with munches ('m'): Map Optimal Munched Route 1 2 3 4 5 6 <-col 1 2 3 4 5 6 <-col 1 B . . . * . 1 B m m m * . 2 . . * . . . 2 . . * m m m 3 . * * . * . 3 . * * . * m 4 . . * * * . 4 . . * * * m 5 * . . * . C 5 * . . * . m Bessie munched 9 squares. Given a map, determine how many squares Bessie will eat on her shortest route to the barn (there's no grass to eat on the barn's square).

 

输入要求

* Line 1: Two space-separated integers: R and C

* Lines 2..R+1: Line i+1 describes row i with C characters (and no spaces) as described above

 

输出要求

* Line 1: A single integer that is the number of squares of grass that Bessie munches on the shortest route back to the barn

 

输入样例

5 6

B...*.

..*...

.**.*.

..***.

*..*.C

 

输出样例

9

 

思路分析

这是一道典型的走迷宫问题,从B点开始走到C点,可以用搜索(BFS、DFS)的方法解决问题

但是需要注意的是,在走迷宫问题中,DFS可以解决问题,但效率过低,一般用BFS解决迷宫问题

与普通搜索不同的是,走迷宫涉及方向转换的问题,一般用 X[4] = {0,-1,0,1}, Y[4] = {-1,0,1,0};来对应表示方向的变换(左、上、右、下)

也可以用二维数组表示Dir[4][2];

 

更进一步还有A*算法等,详情参看:https://blog.csdn.net/denghecsdn/article/details/78778769

 

AC代码

1.BFS

#include<stdio.h>
#include<string.h>
#include<queue>
#define MAX 110
using namespace std;
typedef struct
{
    int px;
    int py;
}pt;//位置坐标
char Map[MAX][MAX];//用字符数组纪录地图
int ans[MAX][MAX];//记录从起点到达地图上每一点所需消耗的步数
int row,column;//行、列
int bgx,bgy,edx,edy;//起点与终点坐标
int X[4] = {0,-1,0,1}, Y[4] = {-1,0,1,0};//代表方向的变换(左、上、右、下)



void BFS()
{
     queue<pt>que;//队列
     int i,j,xn,yn;
     
     pt Bg;
     Bg.px = bgx;
     Bg.py = bgy;//结构体记录开始坐标
     
    for(i = 0; i < row; i++)
        for(j = 0; j < column; j++)
        {
            ans[i][j] = MAX*MAX;//步数足够大
        }
     ans[bgx][bgy] = 0;//起点步数为0
     
     que.push(Bg);//将起点放入队列

     while(!que.empty())//队列无成员,无路可走,结束循环
     {
         
        pt flag;
        flag = que.front();//读取队列最上方成员
        que.pop();//将其移出队列
        if(flag.px == edx&&flag.py == edy)//到达终点结束循环
            break;
        for(i = 0; i < 4; i++)//向四方搜索
    {
        xn = flag.px + X[i];
        yn = flag.py + Y[i];

        if(xn >= 0&&xn < row&&yn >= 0&&yn < column&&Map[xn][yn]!='*'&&ans[xn][yn]==MAX*MAX)
        {
            pt pt1 = {xn,yn};
            que.push(pt1);
            ans[xn][yn] = ans[flag.px][flag.py] + 1;//步数+1
        }
    }
    }
}
int main()
{
    int i,j;
    char ch;
    scanf("%d %d",&row,&column);
    for(i = 0; i < row; i++)
    {
        scanf("%s",Map[i]);
    }

    for(i = 0; i < row; i++)
        for(j = 0 ; j < column; j++)
    {
        ch = Map[i][j];
        if(ch == 'B')
        {
            bgx = i;
            bgy = j;
        }
        if(ch == 'C')
        {
            edx = i;
            edy = j;
        }
    }
    BFS();
    printf("%d\n",ans[edx][edy]);//打印到达终点所需要的步数
    return 0;
}

 

2.DFS

仅供参考,在测试数据较多时会因为超时而提交失败

#include<stdio.h>
#include<string.h>
#define MAX 110
#define Inf 10010
char roadmap[MAX][MAX];
int ans = 0;
int ans1[MAX] = {0};
int wnum = 0;//记录方法数
int vis[MAX][MAX] = {0};//坐标是否访问
int bgx,bgy,edx,edy;//起点和终点坐标
int row,column;//行、列
int X[4] = {0,-1,0,1}, Y[4] = {-1,0,1,0};//方向变换
void DFS(int bg1,int bg2)
{
    int i,j,xn,yn;
    if(bg1==edx&&bg2==edy)
    {
        ans1[wnum++] = ans;
    }
    
    for( i = 0; i < 4; i++)
    {
        xn = bg1 + X[i];
        yn = bg2 + Y[i];
        if(roadmap[xn][yn]!='*' && vis[xn][yn] == 0&&xn >= 0&&xn < row&&yn >= 0 && yn <column)
        {
                ans++;//步数+1
                vis[xn][yn] = 1;//标记下一步已经访问
                DFS(xn,yn);//从下一步开始向下搜索
                vis[xn][yn] = 0;//标记下一步为未访问-》用于回溯到此步后能够往其他方向搜索
                ans--;//步数-1
        }
    }

}
int main()
{
    int x = 0,y = 0;
    int minnum = Inf;
    int i,j;
    char ch;
    memset(roadmap,0,sizeof(roadmap));
    scanf("%d %d",&row,&column);
    for(i = 0; i < row; i++)
    {
        scanf("%s",roadmap[i]);
    }
    for(i = 0; i < row; i++)
        for(j = 0; j < column; j++)
        {
            ch = roadmap[i][j];
            if(ch == 'B')
            {
                bgx = i;
                bgy = j;
            }
            if(ch == 'C')
            {
                edx = i;
                edy = j;
            }
        }

        vis[bgx][bgy] = 1;//标记起始点为已经访问
        DFS(bgx,bgy);
        for(i = 0; i < wnum; i++)//找出最小
        {
            if(minnum > ans1[i])
            minnum = ans1[i];
        }
        printf("%d\n",minnum);
        return 0;
}

 

总结和分析

1.对于走迷宫问题一般用BFS解决,DFS效率太低

2.设置方向转换的数组能更加简洁方便的表示方向的变换

3.如果用DFS解决问题需要注意,应该将起点设置为已经访问,而且在往下搜索后,应该将前一点置为未访问,才能回溯到这点,继续往其他方向访问。

4.有趣的关于 using namespace std https://blog.csdn.net/quyafeng2011/article/details/68921750

以及关于C++中pair 的用法,可用来表示坐标位置 https://blog.csdn.net/sinat_35121480/article/details/54728594

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值