标签:取出 bsp 保存 std inpu 邻接 大小 上下左右 push
题目详情
Description
给定一个大小为 N * M 的迷宫。迷宫由通道和墙壁组成,每一步可以向邻接的上下左右四格的通道移动。请求出从起点到终点所需的最小步数
限制条件:
N,M <= 100
Input
输入两个数字 N 和 M,分别表示迷宫的长和宽,用空格隔开
输入代表迷宫的字符串,N 行 M 列,由 ‘#‘,‘~‘,‘S‘,‘G‘ 组成,分别表示墙壁,通道,起点,终点
Output
从起点到终点所需的最小步数
Sample Input
10 10
#S######.#
......#..#
.#.##.##.#
.#........
##.##.####
....#....#
.#######.#
....#.....
.####.###.
....#...G#
Sample Output
22
#include<iostream> #include<cstdio> #include<queue> using namespace std; const int INF=100000000; const int MAX_N=100+5,MAX_M=100+5; typedef pair<int,int> P; //把 pair看作结构体,typedef的用法,P就是该结构体的一个实例。该"结构体"内只有两个元素 //输入 char a[MAX_N][MAX_M]; //表示迷宫的字符串数组 int N,M; //迷宫的长宽 int sx,sy; //起点坐标 int gx,gy; //终点坐标 int d[MAX_N][MAX_M]; //存放到各个位置的最短距离的数组 //向四个方向移动的向量:右、上、左、下 int dx[4]={1,0,-1,0}; //dx[i]是向量的横坐标 int dy[4]={0,1,0,-1}; //dy[i]是向量的纵坐标 //从(sx,sy)到(gx,gy)的最短距离。如果无法到达,则是INF int bfs(){ queue<P> que; for(int i=0;i<N;++i){ for(int j=0;j<M;++j){ d[i][j]=INF; //把所有位置的距离初始化为INF } } //将起点加入队列,并把这一地点的距离设置为0 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){ //移动后的位置记为 (nx,ny) int nx=p.first+dx[i],ny=p.second+dy[i]; //判断是否可以移动,是否已经访问过该点(d[nx][ny]!=INF即为访问过) if(0<=nx && nx<N && 0<=ny && ny<M && a[nx][ny]!=‘#‘ && d[nx][ny]==INF){ //如果能够移动则加入队列,且到该位置的距离变成到 p 的距离 +1 que.push(P(nx,ny)); d[nx][ny]=d[p.first][p.second]+1; } } } return d[gx][gy]; } int main(){ scanf("%d%d",&N,&M); for(int i=0;i<N;++i){ scanf("%s",a[i]); } for(int i=0;i<N;++i){ for(int j=0;j<M;++j){ if(a[i][j]==‘S‘){ sx=i; sy=j; } if(a[i][j]==‘G‘){ gx=i; gy=j; } } } int res=bfs(); printf("%d",res); return 0; }
本题中,状态是目前所在位置的坐标,可以构造成 pair 或者编码成 int 来表达状态。当状态更加复杂时,需要封装成一个类来表示
宽度优先搜索中,只要将已经访问过的状态用标记管理起来,就可以很好的做到由近及远的搜索。本题要求最短距离,可用 d[N][M] 数组保存。初始化时用充分大的常数 INF 初始化它,这样尚未到达的位置就是 INF,同时起到标记的作用
到达终点时就会停止搜索,如果继续搜索下去直到队列为空,可以计算出到各个位置的最短距离。如果搜索到最后,d 依然是 INF,这个位置就无法从起点到达
宽度优先搜索可以用来求最短路径,最少操作之类的问题
对于同一个状态,宽度优先搜索只经过一次,因此时间复杂度:O(状态数 * 转移的方式)
宽度优先搜索与深度优先搜索类似,从某个状态出发,探索所有可以到达的状态。不同之处在于,宽度优先搜索总是先搜索距离初始状态近的状态
深度优先搜索利用栈进行计算,宽度优先搜索则利用了队列。搜索时首先将初始状态加到队列里,此后从队列的最前端不断取出状态,把从该状态可以转移到的状态中尚未访问过的部分加入队列,如此往复,直至队列为空或找到了问题的解
宽度优先搜索会把状态逐个加入队列,通常需要与状态数成正比的内存空间。反之,深度优先搜索与最大的递归深度成正比。一般与状态数相比,递归的深度不会太大,所以可以认为深度优先搜索更加节省内存
标签:取出 bsp 保存 std inpu 邻接 大小 上下左右 push
原文地址:https://www.cnblogs.com/E-mperor/p/11336293.html