题目:

给定一个大小为 N×M 的迷宫。迷宫由通道和墙壁组成,每一步可以向邻接的上下左右四格

的通道移动。请求出从起点到终点所需的最小步数。请注意,本题假定从起点一定可以移动

到终点。

限制条件;N, M ≤ 100

测试样例:

N=10, M=10(迷宫如下图所示。 '#', '.', 'S', 'G'分别表示墙壁、通道、起点和终点)

#S######.#
......#..#
.#.##.##.#
.#........
##.##.####
....#....#
.#######.#
....#.....
.####.###.
....#...G#

输出结果:

22

关于深度优先搜索我在之前的博客中有提及:深度优先搜索初尝试

以及小z的房子

那么这道题目能不能用深度优先搜索解决呢?

很遗憾,深度优先搜索做不到。

在经过三次尝试以后,得出了DFS解此题的几大缺陷

  • 1.深度优先搜索,顾名思义,对一条可能的路径搜索至无法在搜索,再对下一条路径进行搜索。那么当利用栈来进行DFS搜索,记录最短路径的步数,怎么实现?就算你把已经搜索过的位置标记,再利用标记来减去多余的步数,实现的语句也是非常亘长和麻烦的。
  • 2.那么我用队列来存储可以吗?在第一点,大部分实现DFS算法都是利用栈,那么也带来了一定的麻烦,你经过的每一点都被压入栈中,并且因为栈的后进先出(LIFO),导致每一次搜索分支结束以后,返回的时候(如果没有找到终点),都需要退栈。如果使用队列的话就不会这么麻烦。

    那么用队列实现的“特别的”DFS算法,能不能行的通?答案也是否定的,原因也是因为记录最短路径的步数问题,每次压入队列都有多个坐标。读者可以自己画一个队列进行模拟。
  • 3.DFS搜索到的路径未必是最短的。如果有两条路径可以抵达终点,那么DFS最初所选择的路径未必是最短的。

用BFS(queue)来实现:

代码:

#include<cstdio>
#include<stdlib.h>
#include<iostream>
#include<string>
#include<queue>
#define INF 1000;//定义INF;
using namespace std;
struct p
{
int x,y;
};//存储坐标 int k;
int n,m; int change[6][3]={{1,0},{-1,0},{0,1},{0,-1}};
char pla[105][105];
int dpla[105][105];//存储每一点距离的数组 void BFS(int beginx,int beginy)
{
int i,j;
queue<p>q;//存储坐标的队列 p begin,between;
begin.x=beginx;
begin.y=beginy; q.push(begin); for(i=1;i<=n;i++)
{
for(j=1;j<=m;j++)
{
dpla[i][j]=INF;//所有位置的距离初始化为INF;
}
} dpla[begin.x][begin.y]=0;//开始的地方设置为0;
pla[begin.x][begin.y]='z';//用'z'替换掉原来的‘.’防止走回去 while(!q.empty())
{
begin=q.front();//取出队首开始搜索
q.pop();
if(pla[begin.x][begin.y]=='g')break;//遇到终点break; for(i=0;i<4;i++)
{
between.x=begin.x+change[i][0];
between.y=begin.y+change[i][1];//上下左右搜索 if(between.x>0 && between.x<=n && between.y>0 && between.y<=m)
{
if(pla[between.x][between.y]=='.')
{
q.push(between);//入列
//在dpla记录每一个坐标的距离
dpla[between.x][between.y]=dpla[begin.x][begin.y]+1; pla[between.x][between.y]='z';//字符替换,声明已经走过
}
if(pla[between.x][between.y]=='G')//遇到终点
{
q.push(between);//终点入列;
//记录至终点的距离
dpla[between.x][between.y]=dpla[begin.x][begin.y]+1; pla[between.x][between.y]='g';//用g替换G,代表搜索到终点;
}
}
} } } int main()
{
int i,j;
scanf("%d%d",&n,&m); getchar();//回车
for(i=1;i<=n;i++)
{
for(j=1;j<=m;j++)
{
scanf("%c",&pla[i][j]);
}
getchar();
} for(i=1;i<=n;i++)
{
for(j=1;j<=m;j++)
{
if(pla[i][j]=='S')//找到出发点;
BFS(i,j);
}
} //下面注释的代码判断距离有没有出错
/*for(i=1;i<=n;i++)
{
for(j=1;j<=m;j++)
{
printf("%d ",dpla[i][j]);
}
printf("\n");
}*/ for(i=1;i<=n;i++)
{
for(j=1;j<=m;j++)
{
if(pla[i][j]=='g')
printf("%d",dpla[i][j]);//输出终点记录的距离;
}
} return 0;
}

主要注意的地方和变量的名称我在代码中作了注释。写起来其实和DFS差不多,一个明显不同的地方就是用了一个数组dpla存储每一个坐标与原点坐标的距离。

我在敲这段程序的时候,犯了一个错误:忘记对搜索过的区域.进行字符的替换,这样会导致循环无法结束。

昭锡对BFS也有作一篇文章:迷宫问题

关于DFS和BFS深入的理解及其他:BFS和DFS算法介绍与实现 作者:yousheng324。

2016/3/16

BFS-迷宫问题-用宽度(广度)优先搜索解决最优路径问题的更多相关文章

  1. 【算法入门】广度/宽度优先搜索(BFS)

    广度/宽度优先搜索(BFS) [算法入门] 1.前言 广度优先搜索(也称宽度优先搜索,缩写BFS,以下采用广度来描述)是连通图的一种遍历策略.因为它的思想是从一个顶点V0开始,辐射状地优先遍历其周围较 ...

  2. 层层递进——宽度优先搜索(BFS)

    问题引入 我们接着上次“解救小哈”的问题继续探索,不过这次是用宽度优先搜索(BFS). 注:问题来源可以点击这里 http://www.cnblogs.com/OctoptusLian/p/74296 ...

  3. 搜索与图论②--宽度优先搜索(BFS)

    宽度优先搜索 例题一(献给阿尔吉侬的花束) 阿尔吉侬是一只聪明又慵懒的小白鼠,它最擅长的就是走各种各样的迷宫. 今天它要挑战一个非常大的迷宫,研究员们为了鼓励阿尔吉侬尽快到达终点,就在终点放了一块阿尔 ...

  4. 【BFS宽度优先搜索】

    一.求所有顶点到s顶点的最小步数   //BFS宽度优先搜索 #include<iostream> using namespace std; #include<queue> # ...

  5. BFS算法的优化 双向宽度优先搜索

    双向宽度优先搜索 (Bidirectional BFS) 算法适用于如下的场景: 无向图 所有边的长度都为 1 或者长度都一样 同时给出了起点和终点 以上 3 个条件都满足的时候,可以使用双向宽度优先 ...

  6. 算法基础⑦搜索与图论--BFS(宽度优先搜索)

    宽度优先搜索(BFS) #include<cstdio> #include<cstring> #include<iostream> #include<algo ...

  7. 深度优先dfs与广度bfs优先搜索总结+例题

    DFS(Deep First Search)深度优先搜索 深度优先遍历(dfs)是对一个连通图进行遍历的算法.它的思想是从一个顶点开始,沿着一条路一直走到底,如果发现不能到达目标解,那就返回到上一个节 ...

  8. 宽度优先搜索--------迷宫的最短路径问题(dfs)

    宽度优先搜索运用了队列(queue)在unility头文件中 源代码 #include<iostream>#include<cstdio>#include<queue&g ...

  9. 挑战程序2.1.5 穷竭搜索>>宽度优先搜索

    先对比一下DFS和BFS         深度优先搜索DFS                                   宽度优先搜索BFS 明显可以看出搜索顺序不同. DFS是搜索单条路径到 ...

随机推荐

  1. ABP项目创建

    第一种:1.在MyAbp.Migrator下面的appsettings.json里面的sql连接语句 MyAbp.Web.Host 下面的appsettings.json 里面的连接语句2.把MyAb ...

  2. cookie和session的使用

    http://www.cnblogs.com/linguoguo/p/5106618.html 1:在控制器中添加session和cookie @RequestMapping("/getin ...

  3. [vue]计算和侦听属性(computed&watch)

    先看一下计算属性 vue只有data区的数据才具备响应式的功能. 计算和侦听属性 - v-text里可以写一些逻辑 <div id="example"> {{ mess ...

  4. How to enable TLS 1.2 on Windows Server 2008 R2

    Problem How to enable TLS 1.2 on Windows Server 2008 R2? Resolution QuoVadis recommends enabling and ...

  5. PHP查询MySQL大量数据的内存占用分析

    这篇文章主要是从原理, 手册和源码分析在PHP中查询MySQL返回大量结果时, 内存占用的问题, 同时对使用MySQL C API也有涉及. 昨天, 有同事在PHP讨论群里提到, 他做的一个项目由于M ...

  6. 76. Minimum Window Substring(hard 双指针)

    Given a string S and a string T, find the minimum window in S which will contain all the characters ...

  7. Intro to Python for Data Science Learning 7 - 2D NumPy Arrays

    2D NumPy Arrays from:https://campus.datacamp.com/courses/intro-to-python-for-data-science/chapter-4- ...

  8. linux常用命令:chmod 命令

    chmod命令用于改变linux系统文件或目录的访问权限.用它控制文件或目录的访问权限.该命令有两种用法.一种是包含字母和操作符表达式的文字设定法:另一种是包含数字的数字设定法. Linux系统中的每 ...

  9. 【封装函数】原生js 获取行内外联样式-兼容IE

    var dom=document.getElementsByTagName("div")[0]; console.log(getStyle(dom,"padding-to ...

  10. linux服务器---安装swat

    安装swat swat是一个图形化的samba管理软件,可以帮助不熟悉的人去灵活的配置samba服务, 1.安装swat [root@localhost wj]#yum install -y samb ...