【广度优先搜索】1976: 仙岛求药

题目描述

少年李逍遥的婶婶病了,王小虎介绍他去一趟仙灵岛,向仙女姐姐要仙丹救婶婶。叛逆但孝顺的李逍遥闯进了仙灵岛,克服了千险万难来到岛的中心,发现仙药摆在了迷阵的深处。迷阵由M×N个方格组成,有的方格内有可以瞬秒李逍遥的怪物,而有的方格内则是安全。现在李逍遥想尽快找到仙药,显然他应避开有怪物的方格,并经过最少的方格,而且那里会有神秘人物等待着他。现在要求你来帮助他实现这个目标。

下图 显示了一个迷阵的样例及李逍遥找到仙药的路线。

输入

输入有多组测试数据. 每组测试数据以两个非零整数 M 和 N 开始,两者均不大于20。M 表示迷阵行数, N 表示迷阵列数。接下来有 M 行, 每行包含N个字符,不同字符分别代表不同含义:
1)‘@’:少年李逍遥所在的位置;
2)‘.’:可以安全通行的方格;
3)‘#’:有怪物的方格;
4)‘*’:仙药所在位置。
当在一行中读入的是两个零时,表示输入结束。

输出

对于每组测试数据,分别输出一行,该行包含李逍遥找到仙药需要穿过的最少的方格数目(计数包括初始位置的方块)。如果他不可能找到仙药, 则输出 -1。

样例输入

复制

8 8
.@##...#
#....#.#
#.#.##..
..#.###.
#.#...#.
..###.#.
...#.*..
.#...###
6 5
.*.#.
.#...
..##.
.....
.#...
....@
9 6
.#..#.
.#.*.#
.####.
..#...
..#...
..#...
..#...
#.@.##
.#..#.
0 0
样例输出

复制

10
8
-1

代码如下

#include <iostream>

#include <vector>

#include <queue>

#include <unordered_set>

#include <sstream>



using namespace std;



int bfs(vector<vector<char>>& grid, pair<int, int> start) {

    int rows = grid.size();

    int cols = grid[0].size();

    vector<pair<int, int>> directions = {{1, 0}, {-1, 0}, {0, 1}, {0, -1}};

    queue<pair<int, int>> q;

    unordered_set<string> visited;

    q.push(start);

    visited.insert(to_string(start.first) + "," + to_string(start.second));

    int steps = 0;



    while (!q.empty()) {

        int size = q.size();

        for (int i = 0; i < size; i++) {

            auto [x, y] = q.front();

            q.pop();



            if (grid[x][y] == '*') {

                return steps;

            }



            for (const auto& dir : directions) {

                int nx = x + dir.first;

                int ny = y + dir.second;



                if (nx >= 0 && nx < rows && ny >= 0 && ny < cols &&

                    visited.find(to_string(nx) + "," + to_string(ny)) == visited.end() &&

                    grid[nx][ny] != '#') {

                    visited.insert(to_string(nx) + "," + to_string(ny));

                    q.push({nx, ny});

                }

            }

        }

        steps++;

    }



    return -1;

}



int findShortestPath(vector<vector<char>>& grid) {

    for (int i = 0; i < grid.size(); i++) {

        for (int j = 0; j < grid[i].size(); j++) {

            if (grid[i][j] == '@') {

                return bfs(grid, {i, j});

            }

        }

    }

    return -1;

}



int main() {

    string input = R"(

8 8

.@##...#

#....#.#

#.#.##..

..#.###.

#.#...#.

..###.#.

...#.*..

.#...###

6 5

.*.#.

.#...

..##.

.....

.#...

....@

9 6

.#..#.

.#.*.#

.####.

..#...

..#...

..#...

..#...

#.@.##

.#..#.

0 0)";



    istringstream reader(input);

    string line;



    while (getline(reader, line)) {

        istringstream iss(line);

        int M, N;

        if (!(iss >> M >> N)) break;

        if (M == 0 && N == 0) break;



        vector<vector<char>> grid(M, vector<char>(N));

        for (int i = 0; i < M; i++) {

            getline(reader, line);

            for (int j = 0; j < N; j++) {

                grid[i][j] = line[j];

            }

        }



        int result = findShortestPath(grid);

        cout << result << endl;

    }



    return 0;

}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

呱呱呱~

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值