蒜头君回家(bfs)
题干:蒜头君要回家,但是他家的钥匙在他的朋友花椰妹手里,他要先从花椰妹手里取得钥匙才能回到家。花椰妹告诉他:“你家的钥匙被我复制了很多个,分别放在不同的地方。”
蒜头君希望能尽快回到家中,他首先需要取得任意一把钥匙,请你帮他计算出回家所需要的最短路程。
蒜头君生活的城市可以看做是一个n×m 的网格,其中有道路有障碍,钥匙和家所在的地方可以看做是道路,可以通过。蒜头君可以在城市中沿着上下左右 4 个方向移动,移动一个格子算做走一步。
输入格式
第一行有两个整数 n,m。城市的地图是 n 行 m 列。(1≤n,m≤2000)
接下来的 n 行,每行 m 个字符,代表城市的地图。'.'代表道路,'#'代表障碍物,'S'代表蒜头君所在的位置,'T'代表蒜头家的位置,'P'代表钥匙的位置。除了障碍物以外,别的地方都可以通过。题目保证蒜头君至少有一条路径可以顺利拿到钥匙并且回家。
输出格式
输出蒜头回家要走的最少步数,占一行。
样例输入
8 10
P.####.#P#
..#..#...#
..#T##.#.#
..........
..##.#####
..........
#####...##
###....S##
样例输出
21
#include#include #include using namespace std; int n, m; class point { public: point(int sx, int sy, int snum, int sflag) { this->x = sx; this->y = sy; this->num = snum; this->flag = sflag; } int x, y; int num, flag; };//存储结构,包含点坐标,到该点所走的步数以及该点的层级->(找到钥匙前为第0层,找到钥匙变为第1层) int head[4][2] = {{-1, 0}, {1, 0}, {0, -1}, {0, 1}};//四方向搜索 char map1[2001][2001];//存储地图 int visit[2001][2001][2] = {0};//visit多一个维度用来表示层数(每个点每层都可经过一次) void bfs(int &x, int &y) { queue q;//队列 q.push(point(x, y, 0, 0)); visit[x][y][0] = 1; while (!q.empty())//非空循环 { point t = q.front(); q.pop(); if (map1[t.x][t.y] == 'T' && t.flag == 1)//在第1层找到终点,退出(进入第一层也就是,保证拿到了钥匙) { cout << t.num; return; } if (map1[t.x][t.y] == 'P')//拿到钥匙,标记改为第1层 t.flag = 1; for (int i = 0; i < 4; i++) { int jx = t.x + head[i][0]; int jy = t.y + head[i][1];//遍历四周同深度点 if (jx < 0 || jx >= n || jy < 0 || jy >= m)//越界就重开 continue; if (!visit[jx][jy][t.flag] && map1[jx][jy] != '#')//该层没来过且不是障碍,就在这层标记该点,并入队 { visit[jx][jy][t.flag] = 1; q.push(point(jx, jy, t.num + 1, t.flag));//深度(步数)加1 } } } } int main() { cin >> n >> m; int tx, ty; for (int i = 0; i < n; i++) //思路:先第一层找到钥匙 ,再从钥匙处第二层找家(bfs最先找到的就是最近的) { for (int j = 0; j < m; j++) { cin >> map1[i][j]; if (map1[i][j] == 'S')//找到入口做好记录 { tx = i; ty = j; } } } bfs(tx, ty); return 0; }