题目描述
链接地址:http://bailian.openjudge.cn/practice/4129/
4129:变换的迷宫
总时间限制: 1000ms 内存限制: 65536kB
描述
你现在身处一个R*C 的迷宫中,你的位置用"S" 表示,迷宫的出口用"E" 表示。
迷宫中有一些石头,用"#" 表示,还有一些可以随意走动的区域,用"." 表示。
初始时间为0 时,你站在地图中标记为"S" 的位置上。你每移动一步(向上下左右方向移动)会花费一个单位时间。你必须一直保持移动,不能停留在原地不走。
当前时间是K 的倍数时,迷宫中的石头就会消失,此时你可以走到这些位置上。在其余的时间里,你不能走到石头所在的位置。
求你从初始位置走到迷宫出口最少需要花费多少个单位时间。
如果无法走到出口,则输出"Oop!"。
输入
第一行是一个正整数 T,表示有 T 组数据。
每组数据的第一行包含三个用空格分开的正整数,分别为 R、C、K。
接下来的 R 行中,每行包含了 C 个字符,分别可能是 "S"、"E"、"#" 或 "."。
其中,0 < T <= 20,0 < R, C <= 100,2 <= K <= 10。
输出
对于每组数据,如果能够走到迷宫的出口,则输出一个正整数,表示最少需要花费的单位时间,否则输出 "Oop!"。
样例输入
1
6 6 2
...S..
...#..
.#....
...#..
...#..
..#E#.
样例输出
7
解题思路
这个题目看到首先想到的是使用bfs算法,对于在给定时刻迷宫中的石头消失,使用标记要标记时间,即在某个时间某个位置,因为石头消失的时间只和 mod k有关,标记的大小设置成k就可以了。
解题代码
#include <cstring>
#include <cstdio>
#include <queue>
char maze[110][110];
int flags[110][110][15];
int dx[4] = {0, -1, 0, 1};
int dy[4] = {-1, 0, 1, 0};
int R, C, K;
struct state{
int x, y;
int time;
state(){}
state(int x, int y, int time){this->x = x; this->y = y; this->time = time;}
};
int main(){
int T;
scanf("%d", &T);
while(T--){
scanf("%d %d %d
", &R, &C, &K);
memset(maze, 0, sizeof(maze));
memset(flags, 0, sizeof(flags));
int x = 0, y = 0;
for(int i = 0; i < R; i++){
for(int j = 0; j < C; j++){
scanf("%c", &maze[i][j]);
if(maze[i][j] == 'S'){
x = i;
y = j;
}
}
getchar();
}
std::queue<state> q;
q.push(state(x, y, 0));
flags[x][y][0] = 1;
while(!q.empty()){
state s = q.front();
if(maze[s.x][s.y] == 'E'){
printf("%d
", s.time);
break;
}
else{
for(int i = 0; i < 4; i++){
int x = s.x + dx[i];
int y = s.y + dy[i];
if (0 <= x && x < R && 0 <= y && y < C && (maze[x][y] != '#' || (s.time+1)%K==0)) {
if (flags[x][y][(s.time + 1) % K]) continue;
flags[x][y][(s.time + 1) % K] = 1;
q.push(state(x, y, s.time + 1));
}
}
}
q.pop();
}
if(q.empty()){
printf("Oop!
");
}
}
return 0;
}