【教程】BFS学习笔记

99封情书 提交于 2020-01-10 10:01:22

- 例子(已被授予主人公的名字使用权)

ZZJ 进入了一个 n × m 的迷宫矩阵,执着的他表示要穿过迷宫。

ZZJ 在地图的左上角,而迷宫出口在右下角,设进入每个房间都需要 1 的时间,他在入口的地面上捡到一张迷宫地图,发现有一些障碍物(图中以“障碍”表示,代码中以“#”表示,存在map数组中),于是他决定计算出自己到终点最少需要时间(请思考后再往下看)。

  1 2 3 4 5 6 7
1 起点            
2         障碍    
3     障碍        
4         障碍    
5   障碍         终点

 

- 思路:
- 首先,我们需要一个小本本存ZZJ到达的地方及步数:

1 struct nod{int x,y,t;}f[100001];//x,y表示位置,t表示ZZJ到达此点需要的步数

- 其次,我们需要一个bool数组存i,j这个位置是否被走过以及一个map数组存地图:

1    bool bz[101][101];//这里以0<n,m<=100为数据范围,实际情况请以题面修改数组范围
2    char map[101][101]; 

- 再次,我们需要一个方向数组,使ZZJ能上、下、左、右移动:

1 int dx[4]={0,1,0,-1};
2 int dy[4]={1,0,-1,0}; 

- 准备完毕了,ZZJ可以出发啦!
- 首先,ZZJ将自己的位置存进小本本的第一格里:

1 tou=1,wei=2;//用两个指针指向小本本队头和队尾
2 f[tou].x=1;
3 f[tou].y=1;
4 f[tou].t=0;

- 接着,ZZJ通过方向数组到达一个新位置:

1 int nx=f[tou].x+dx[i];
2 int ny=f[tou].y+dy[i];

- 但是ZZJ有可能跑出了迷宫,掉下悬崖了,所以我们要判断一下ZZJ站在的位置是否在迷宫内:

1 if(nx<1||nx>n||ny<1||ny>m)continue;//跑出去就不要他了
- 如果ZZJ已经到了终点,那就是最短到达的距离啦(因为在这个地图中到达每一个点距离都为1),输出小本本的当前的 `t+1` ,退出搜索就好啦就好啦:
1    if(nx==n&&ny==m) 
2    {
3    printf("ZZJ到达终点的最短距离是:%d",f[tou].t+1);
4    return;
5    } 

- 如果ZZJ到达的是一个新的非障碍的点,并且没来过,ZZJ就在他的小本本上记录下他的位置:

if(map[nx][ny]=='.'&&bz[nx][ny]==false)
{
     bz[nx][ny]=true;
     f[wei].x=nx;
     f[wei].y=ny;
     f[wei].t=f[tou].t+1;
     wei++;
}

- ZZJ走过了(遍历)周围可走的点后,就将小本本的队头往后挪一个,开始了新的遍历(直到没有点可以更新出新的点时停止,即 $tou=wei$ ):

1 tou++;

- 这就是整个bfs的完整过程啦,上完整代码:

 1 #include<cstdio>
 2 int n,m,tou,wei;
 3 int dx[4]={0,1,0,-1};
 4 int dy[4]={1,0,-1,0};
 5 bool bz[101][101];
 6 char map[101][102];
 7 struct nod{int x,y,t;} f[10001];
 8 void bfs(int sx,int sy)
 9 {
10      tou=1,wei=2;
11      f[tou].x=sx;
12      f[tou].y=sy;
13      f[tou].t=0;
14      while(tou<wei)
15      {
16          for(int i=0;i<3;i++)
17          {
18              int nx=f[tou].x+dx[i];
19              int ny=f[tou].y+dy[i];
20              if(nx<1 || nx>n || ny<1 || ny>m)
21                  continue;
22              if(nx==n && ny==m)
23              {
24                  printf("ZZJ到达终点的最短距离是:%d",f[tou].t+1);
25                  return;
26              }
27              if(map[nx][ny]=='.'&&bz[nx][ny]==false)
28              {
29                  bz[nx][ny]=true;
30                  f[wei].x=nx;
31                  f[wei].y=ny;
32                  f[wei].t=f[tou].t+1;
33                  wei++;
34              }
35          }
36          tou++;
37      }
38 }
39 int main()
40 {
41      scanf("%d%d",&n,&m);
42      for(int i=1;i<=n;i++)
43      {
44          for(int j=1;j<=m+1;j++)
45          {
46              scanf("%c",&map[i][j]);//结尾要多读一个换行符
47          }
48      }
49      bfs(1,1);
50      return 0;
51 }

 

- 如果理解透了这道题,就练练手吧:
- [题目练习](http://noi.openjudge.cn/ch0205/2753/)
- 鸣谢: @$\text{zhongzijun}$ 。

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!