DFS/BFS 关于迷宫问题
2017-10-11 10:59
253 查看
DFS和BFS是两种不同的搜索方法。DFS是深度优先,即沿着一条链走直到走不通了为止。BFS是广度优先,搜索的链是以距离向外辐射的。
以一道经典的迷宫图为例来说明这两种搜索方法的用处。
BFS不考虑结果的可能位置,彻底地搜索整张图,而在迷宫问题中,可以求出一个点到另外一个点的最短距离。
而DFS在迷宫的问题中,搜索每一条可能能到的路径,对应的即搜索一个点到另外一个点所有可能的路径。
给定一个迷宫,指明起点和终点,找出从起点出发到终点的有效可行路径,就是迷宫问题(maze problem)。
迷宫可以以二维数组来存储表示。0表示通路,1表示障碍。注意这里规定移动可以从上、下、左、右四方方向移动。坐标以行和列表示,均从0开始,给定起点(0,0)和终点(4,4),迷宫表示如下:
应用的数据结构主要是栈。
关键代码如下:
while (!Q.empty())
{
now = Q.front();
//4个方向
for (int i = 0; i < 4; i++)
{
node temp;
temp.x=now.x + move[i].x;
temp.y = now.y + move[i].y;
//第二个错的地方是mestry[temp.y][temp.x] != 1 这个地方,temp是以坐标方式表示的,而数组的表示和坐标不一样,数组的[][]的前一个相当于y的值,方向是垂直向下增长的
//下面都用坐标和数组统一起来用[Y][X]表示
//满足的条件和上述的DFS差不多
if (temp.x >= 0 && temp.y >= 0 && temp.x <= (m - 1) && temp.y <= (n - 1) && mestry[temp.y][temp.x] != 1&&flag[temp.y][temp.x]==0)
{
//如果这个点符合条件,即在边界内,又是可以走的点
//那就推入队列中,并把这个点的父亲记录下来
Q.push(temp);
flag[temp.y][temp.x] = -1;
//PATH的记录是为了输出具体路径,如果只是算距离或者是否有最短路径则不需要。
path[temp.y][temp.x] = now;
//如果找到了
if (temp.x == want.x&&temp.y == want.y)
find = true;
}
}
Q.pop();
}
如果要输出具体路径的话,把栈里的坐标依次弹出即可。
BFS:
BFS用到的数据结构主要是队列。
用队列能确保是按照相同的距离向外辐射的,这也是广度搜索的思想所在。就如同层序输出二叉树一样。
关键代码如下:
如果只是想找到最短路径那么在FOR循环块的后面加上一个SUM++即可,在判断出找到了这条路后直接BREAK就可以了。
用DFS能生成所有有可能的组合,同时要注意的是回溯,像这里递归完以后要把这个点重新置为未访问。
还有进行剪枝能提高程序运行的速度。
用BFS能找到最短距离,剪枝也能提高程序的运行速度。
如有问题欢迎私信。
以一道经典的迷宫图为例来说明这两种搜索方法的用处。
BFS不考虑结果的可能位置,彻底地搜索整张图,而在迷宫问题中,可以求出一个点到另外一个点的最短距离。
而DFS在迷宫的问题中,搜索每一条可能能到的路径,对应的即搜索一个点到另外一个点所有可能的路径。
给定一个迷宫,指明起点和终点,找出从起点出发到终点的有效可行路径,就是迷宫问题(maze problem)。
迷宫可以以二维数组来存储表示。0表示通路,1表示障碍。注意这里规定移动可以从上、下、左、右四方方向移动。坐标以行和列表示,均从0开始,给定起点(0,0)和终点(4,4),迷宫表示如下:
int maze[5][5]={ {0,0,0,0,0}, {0,1,0,1,0}, {0,1,1,0,0}, {0,1,1,0,1}, {0,0,0,0,0} };用DFS求解即可求得所有的路径。
应用的数据结构主要是栈。
关键代码如下:
while (!Q.empty())
{
now = Q.front();
//4个方向
for (int i = 0; i < 4; i++)
{
node temp;
temp.x=now.x + move[i].x;
temp.y = now.y + move[i].y;
//第二个错的地方是mestry[temp.y][temp.x] != 1 这个地方,temp是以坐标方式表示的,而数组的表示和坐标不一样,数组的[][]的前一个相当于y的值,方向是垂直向下增长的
//下面都用坐标和数组统一起来用[Y][X]表示
//满足的条件和上述的DFS差不多
if (temp.x >= 0 && temp.y >= 0 && temp.x <= (m - 1) && temp.y <= (n - 1) && mestry[temp.y][temp.x] != 1&&flag[temp.y][temp.x]==0)
{
//如果这个点符合条件,即在边界内,又是可以走的点
//那就推入队列中,并把这个点的父亲记录下来
Q.push(temp);
flag[temp.y][temp.x] = -1;
//PATH的记录是为了输出具体路径,如果只是算距离或者是否有最短路径则不需要。
path[temp.y][temp.x] = now;
//如果找到了
if (temp.x == want.x&&temp.y == want.y)
find = true;
}
}
Q.pop();
}
如果要输出具体路径的话,把栈里的坐标依次弹出即可。
BFS:
BFS用到的数据结构主要是队列。
用队列能确保是按照相同的距离向外辐射的,这也是广度搜索的思想所在。就如同层序输出二叉树一样。
关键代码如下:
while (!Q.empty()) { now = Q.front(); for (int i = 0; i < 4; i++) { node temp; temp.x=now.x + move[i].x; temp.y = now.y + move[i].y; //第二个错的地方是mestry[temp.y][temp.x] != 1 这个地方,temp是以坐标方式表示的,而数组的表示和坐标不一样,数组的[][]的前一个相当于y的值,方向是垂直向下增长的 //下面都用坐标和数组统一起来用[Y][X]表示 if (temp.x >= 0 && temp.y >= 0 && temp.x <= (m - 1) && temp.y <= (n - 1) && mestry[temp.y][temp.x] != 1&&flag[temp.y][temp.x]==0) { //如果这个点符合条件,即在边界内,又是可以走的点 //那就推入队列中,并把这个点的父亲记录下来 Q.push(temp); flag[temp.y][temp.x] = -1; path[temp.y][temp.x] = now; if (temp.x == want.x&&temp.y == want.y) find = true; } } Q.pop(); }
如果只是想找到最短路径那么在FOR循环块的后面加上一个SUM++即可,在判断出找到了这条路后直接BREAK就可以了。
用DFS能生成所有有可能的组合,同时要注意的是回溯,像这里递归完以后要把这个点重新置为未访问。
还有进行剪枝能提高程序运行的速度。
用BFS能找到最短距离,剪枝也能提高程序的运行速度。
如有问题欢迎私信。
880b
相关文章推荐
- 关于迷宫问题的dfs与bfs两中求解方式
- poj 迷宫问题(路径记录)(DFS,BFS)
- SDUT 1157-小鼠迷宫问题(BFS&DFS)
- [置顶] 模拟求解迷宫问题(DFS+BFS)
- poj 迷宫问题(路径记录)(DFS,BFS)
- 【POJ】3984 迷宫问题 BFS 与 DFS
- poj 迷宫问题(路径记录)(DFS,BFS)
- OpenJ_Bailian 4127 迷宫问题(DFS+BFS)
- POJ 3984 迷宫问题 (DFS+BFS)
- SDUT1157:小鼠迷宫问题(bfs+dfs)
- poj 迷宫问题(路径记录)(DFS,BFS)
- 迷宫问题、最短路(BFS,DFS)
- FZU - 1205 小鼠迷宫问题 (bfs+dfs)
- poj 迷宫问题(路径记录)(DFS,BFS)
- POJ - 3984 迷宫问题(BFS、DFS)
- POJ 3984 迷宫问题 BFS DFS两种解法
- poj 迷宫问题(路径记录)(DFS,BFS)
- H - 迷宫问题 POJ3984 (BFS+DFS)
- poj 迷宫问题(路径记录)(DFS,BFS)
- nyoj——58 最小步数(DFS,BFS 迷宫问题)