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;
}