【搜索-广搜】 迷宫的最短路径
2017-02-14 15:13
183 查看
题目:
给定一个大小为N*M的迷宫,由通道('.')和墙壁('#')组成,其中通道S表示起点,通道G表示终点,每一步移动可以达到上下左右中不是墙壁的位置。试求出起点到终点的最小步数。(本题假定迷宫是有解的)(N,M<=100)
样例输入:
10 10
样例输出:
22
这道题目以及解法均来自《挑战程序设计竞赛(第2版)》第34页-36页;
个人觉得这个例题很好地表现了广度优先搜索是如何与队列先进先出(FIFO)的思想联系起来的,通过不断取得某个状态后能够达到的所有状态并将其加入队列, 并且由于队列本身的特性先加入队列的状态总是先得到处理,这样就达到了一个目的:总是先将需要转移次数更少的状态进行分析处理,换句话说就是总是取得了这个状态的树中更接近根部的节点,又或者是总是让搜索树的广度得到尽可能增加。
/*********代码的建立过程**********/
在这个问题中,找到从起点到终点的最短路径其实就是一个建立队列的过程:
1.从起点开始,先将其加入队列,设置距离为0;
2.从队列首端取出位置,将从这个位置能够到达的位置加入队列,并且让这些位置的距离为上一个位置的距离加上1;
3.循环2直到将终点添加到队列中,这说明我们已经找到了路径;
注意到在这个过程中,每次处理的位置所对应的距离是严格递增的,因此一旦找到终点,当时的距离就是最短距离;
同样基于这个原因,搜索可移动到的位置所使用的判断条件中不仅仅是不碰墙壁、不超过边界,还有一个就是没有到达过,因为如果已经到达了这个位置,这说明已经有更短的路径到达这个位置,这次到达这个位置的路径是更差的,不可能得到更好的最终解。
代码:
关于书本的摘录:
(详细见ppt上面的广搜搜索过程)
1.先搜索距离初始状态近的状态;
2.复杂度为O(状态数×转移方式)
3.广搜运用了队列,搜索的时候首先将初始状态加入队列里,此后从队列的最前端取出状态,把从该状态可以转移到的且尚未访问过的部分加入队列,如此往复,直至队列被取空或找到了问题的解;
4.适用于找最短路径,最少操作数;
给定一个大小为N*M的迷宫,由通道('.')和墙壁('#')组成,其中通道S表示起点,通道G表示终点,每一步移动可以达到上下左右中不是墙壁的位置。试求出起点到终点的最小步数。(本题假定迷宫是有解的)(N,M<=100)
样例输入:
10 10
样例输出:
22
这道题目以及解法均来自《挑战程序设计竞赛(第2版)》第34页-36页;
个人觉得这个例题很好地表现了广度优先搜索是如何与队列先进先出(FIFO)的思想联系起来的,通过不断取得某个状态后能够达到的所有状态并将其加入队列, 并且由于队列本身的特性先加入队列的状态总是先得到处理,这样就达到了一个目的:总是先将需要转移次数更少的状态进行分析处理,换句话说就是总是取得了这个状态的树中更接近根部的节点,又或者是总是让搜索树的广度得到尽可能增加。
/*********代码的建立过程**********/
在这个问题中,找到从起点到终点的最短路径其实就是一个建立队列的过程:
1.从起点开始,先将其加入队列,设置距离为0;
2.从队列首端取出位置,将从这个位置能够到达的位置加入队列,并且让这些位置的距离为上一个位置的距离加上1;
3.循环2直到将终点添加到队列中,这说明我们已经找到了路径;
注意到在这个过程中,每次处理的位置所对应的距离是严格递增的,因此一旦找到终点,当时的距离就是最短距离;
同样基于这个原因,搜索可移动到的位置所使用的判断条件中不仅仅是不碰墙壁、不超过边界,还有一个就是没有到达过,因为如果已经到达了这个位置,这说明已经有更短的路径到达这个位置,这次到达这个位置的路径是更差的,不可能得到更好的最终解。
代码:
#include<cstdio> #include<cstring> #include<queue> #include<algorithm> using namespace std; typedef pair<int ,int> P; const int inf=100000000; int n,m; char maze[110][110]; int sx,sy,gx,gy; int dx[4]= {0,1,0,-1},dy[4]= {1,0,-1,0}; int d[110][110]; int bfs() { for(int i=0; i<n; i++) for(int j=0; j<m; j++) d[i][j]=inf; queue<P> que; que.push(P(sx,sy)); d[sx][sy]=0; while(que.size()) { P p=que.front(); que.pop(); if(p.first==gx&&p.second==gy) break; for(int i=0; i<4; i++) { int nx=p.first+dx[i],ny=p.second+dy[i]; if(nx>=0&&nx<n&&ny>=0&&ny<m&&d[nx][ny]==inf&&maze[nx][ny]!='#') d[nx][ny]=d[p.first][p.second]+1,que.push(P(nx,ny)); } } return d[gx][gy]; } int main() { scanf("%d%d",&n,&m); for(int i=0; i<n; i++) scanf("%s",maze[i]); for(int i=0; i<n; i++) for(int j=0; j<m; j++) { if(maze[i][j]=='S') sx=i,sy=j; if(maze[i][j]=='G') gx=i,gy=j; } int ans=bfs(); printf("%d\n",ans); return 0; }
关于书本的摘录:
(详细见ppt上面的广搜搜索过程)
1.先搜索距离初始状态近的状态;
2.复杂度为O(状态数×转移方式)
3.广搜运用了队列,搜索的时候首先将初始状态加入队列里,此后从队列的最前端取出状态,把从该状态可以转移到的且尚未访问过的部分加入队列,如此往复,直至队列被取空或找到了问题的解;
4.适用于找最短路径,最少操作数;
相关文章推荐
- 迷宫问题(广度优先搜索,输出最短路径)
- 重学搜索yi.3:迷宫的最短路径--bfs
- 迷宫最短路径 深度优先搜索—C—python
- 迷宫最短路径(宽度搜索妙解)
- 广度优先搜索迷宫的最短路径走法!
- 宽度优先搜索——迷宫的最短路径
- (广度优先搜索第一课)迷宫的最短路径 - BFS
- 搜索最短路径:迷宫问题 POJ - 3984
- 迷宫:广度优先搜索求最短路径
- 《挑战程序设计比赛》 P35 题目:迷宫的最短路径 广度搜索
- 找到迷宫的所有路径和最短路径-深度搜索
- 搜索入门(BFS)迷宫的最短路径
- 白书2.1.5宽度优先搜索(迷宫的最短路径)
- 广度优先搜索--迷宫最短路径--队列
- 在SQL Server实现最短路径的搜索
- BFS 模板 【迷宫的最短路径】
- 也谈迷宫算法(最短路径 队列)+源程序
- AStar算法求解迷宫最短路径问题
- POJ-3984迷宫问题(典型BFS找最短路径)
- 图论, 1.各种方案的最短路径,最小生成树,拓扑排序, 2.隐式图的搜索,N-皇后问题,数独,马踏棋盘,中文划分,回文划分.