地下城与勇士(C++语言)

文章讲述了龙神在一个由道路、墙壁和随机消失的怪物构成的迷宫中,寻找在避开所有怪物的情况下到达出口的最短时间。使用动态规划方法解决此路径问题。
摘要由CSDN通过智能技术生成

Description
龙神觉得无聊于是来到了地下城,这里是一个巨大的迷宫,有一些可以通行的路、一些不可以通行的墙,还有一些怪物。虽然龙神可以轻易地干掉这些怪物,但他觉得这样就太没意思了,他观察到这些怪物每 k 秒会消失一次(例如 k = 3 时,则第 3, 6, 9, … ,秒怪物是消失的),每一秒龙神可以选择向上下左右行走一步(不能在原地不动)。龙神想知道在避开全部怪物的条件下,到达出口所需要的最短时间。

Input
第一行输入一个整数 T ( 1 ≤ T ≤ 10 ),代表用例组数。
每组用例的第一行包括三个整数 n , m ( 1 ≤ n , m ≤ 100 ) 和 ,k ( 1 ≤k ≤ 50 )分别表示地下城迷宫的行数、列数、怪物的消失间隔。
接下来的 n 行代表迷宫,.表示可以通行的路,#表示墙,*表示怪物,S表示起点,E代表出口。

Output
输出一个整数,表示龙神走出地下城迷宫的最短时间,如果龙神不能走出迷宫则输出-1。

Source
BITACM2018第一轮积分赛(三)- Problem J


样例

输入(1)

1
6 6 2
...S..
...#..
.#....
...#.#
...*..
..*E*.

输出(1)

7

代码

#include <iostream>
#include <vector>
#include <queue>

using namespace std;

struct Point {
    int x;
    int y;

    Point(int x_, int y_) : x(x_), y(y_) {}

    Point() {}
};

struct Step {
    int x;
    int y;
    int steps;

    Step(int x_, int y_, int steps_) : x(x_), y(y_), steps(steps_) {}

    Step() {}
};

const int MAX_N = 200;
const int MAX_M = 200;
const int MAX_K = 50;

int main() {
    int T;
    cin >> T;

    while (T--) {
        int n, m, k;
        cin >> n >> m >> k;
        char Maze[MAX_N][MAX_M];
        vector<vector<vector<bool>>> visited(n, vector<vector<bool>>(m, vector<bool>(k, false)));

        Point PointStart, PointEnd;

        // Input the maze and find start and end points
        for (int i = 0; i < n; i++) {
            for (int j = 0; j < m; j++) {
                cin >> Maze[i][j];
                if (Maze[i][j] == 'S') {
                    Maze[i][j] = '.';
                    PointStart.x = j;
                    PointStart.y = i;
                }
                if (Maze[i][j] == 'E') {
                    Maze[i][j] = '.';
                    PointEnd.x = j;
                    PointEnd.y = i;
                }
            }
        }

        int MIN = 1 << 30;
        queue<Step> q;
        q.push(Step(PointStart.x, PointStart.y, 0));

        while (!q.empty()) {
            Step tmp = q.front();
            int currentX = tmp.x;
            int currentY = tmp.y;
            int currentSteps = tmp.steps;

            int dx[] = {0, 0, -1, 1};
            int dy[] = {-1, 1, 0, 0};

            for (int dir = 0; dir < 4; dir++) {
                int newX = currentX + dx[dir];
                int newY = currentY + dy[dir];

                if (newX >= 0 && newX < m && newY >= 0 && newY < n &&
                    Maze[newY][newX] != '#' &&
                    (Maze[newY][newX] != '*' || (Maze[newY][newX] == '*' && (currentSteps + 1) % k == 0))) {

                    if (!visited[newY][newX][(currentSteps + 1) % k]) {
                        visited[newY][newX][(currentSteps + 1) % k] = true;
                        Step returnStep(newX, newY, currentSteps + 1);
                        q.push(returnStep);

                        if (newX == PointEnd.x && newY == PointEnd.y) {
                            if (currentSteps + 1 <= MIN) {
                                MIN = currentSteps + 1;
                            }
                        }
                    }
                }
            }
            q.pop();
        }

        if (MIN == 1 << 30) {
            cout << -1 << endl;
        } else {
            cout << MIN << endl;
        }
    }

    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值