BFS题,大致遵循以下思路:
- 可以设置一个结构体,包含 4 个成员: x, y, step, state。其中 x, y 表示当前处在迷宫中的位置,step 表示到达该位置时总共用了多少步,state 表示无敌状态剩余的步数,state = 0 表示非无敌状态,state > 0 表示处于无敌状态,每走一步就减 1。
- 设置 vis[n][n] 数组, vis[i][j] 记录迷宫位置 i, j 是否被访问过。
- 假设迷宫用 maze[n][n] 表示,当前位置为 curx, cury,当前步数为 step,无敌状态剩余步数为 state。假设下一步位置为 nextx, nexty,按照以下顺序进行判断:
3.1. 如果 nextx, nexty 越界了,或者 maze[n][n] == ‘#’,跳过位置 nextx, nexty;
3.2. 否则,如果 vis[next][nexty] != 0 (未被访问),见 Pseudocode1 说明;
3.3. 否则,见 Pseudocode2 说明。 - 当到达 n, n 时,直接返回到达 n, n 的步数即可,由于 BFS 的辐射状搜索的特点,可以保证此时肯定是到达 n, n 的最少步数,如果到达不了 n, n 就返回 -1 。
""" Pseudocode1 """
if maze[nextx][nexty] == '.':
将位置 (nextx, nexty, step + 1, 0 或 state - 1) 添加进 BFS 队列
vis[nextx][nexty] = True
else if maze[nextx][nexty] == 'X':
// 陷阱只有无敌状态时才能通过, 所以要检查 state 是否为 0
if state > 0:
将位置 (nextx, nexty, step + 1, state - 1) 添加进 BFS 队列
vis[nextx][nexty] = True
else if maze[nextx][nexty] == '%':
将位置 (nextx, nexty, step + 1, K) 添加进 BFS 队列, K 的意义与题目提供的一致
vis[nextx][nexty] = True
""" Pseudocode2 """
if (maze[nextx][nexty] == '.' or maze[nextx][nexty] == 'X') and state > 0:
// state > 0 表示当前正处于无敌状态,无敌状态不受 vis 的影响,只要不是 '#' 和 '%' 就随便走
将位置 (nextx, nexty, step + 1, state - 1) 添加进 BFS 队列
Python 代码:
import sys
from collections import deque
def BFS(n, k, mz):
dirs = [(1, 0), (0, 1), (-1, 0), (0, -1)]
vis = [[False for _ in range(n)] for __ in range(n)]
queue = deque()
endx, endy = n - 1, n - 1
vis[0][0] = True
queue.append((0, 0, 0, 0))
while queue:
curx, cury, step, state = queue.popleft()
if curx == endx and cury == endy:
return step
for i in range(4):
nextx, nexty = curx + dirs[i][0], cury + dirs[i][1]
if nextx < 0 or nextx >= n or nexty < 0 or nexty >= n or mz[nextx][nexty] == '#':
continue
elif not vis[nextx][nexty]:
if mz[nextx][nexty] == '.':
queue.append((nextx, nexty, step + 1, state - 1 if state else 0))
vis[nextx][nexty] = True
elif mz[nextx][nexty] == 'X' and state:
queue.append((nextx, nexty, step + 1, state - 1))
vis[nextx][nexty] = True
else:
queue.append((nextx, nexty, step + 1, k))
vis[nextx][nexty] = True
elif (mz[nextx][nexty] == '.' or mz[nextx][nexty] == 'X') and state:
queue.append((nextx, nexty, step + 1, state - 1))
return -1
N, K = list(map(int, sys.stdin.readline().strip().split()))
maze = []
for i in range(N):
maze.append(sys.stdin.readline().strip())
print(BFS(N, K, maze))
C++ 代码:
#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>
#include<queue>
using namespace std;
const int maxn = 1e3 + 5;
int dirs[4][2] = {{1, 0}, {0, 1}, {-1, 0}, {0, -1}};
char maze[maxn][maxn];
bool vis[maxn][maxn];
struct block{
int x;
int y;
int step;
int state;
block(int x, int y, int step, int state){
this->x = x;
this->y = y;
this->step = step;
this->state = state;
}
};
int BFS(int n, int k){
memset(vis, 0, sizeof(vis));
queue<block> Q;
vis[1][1] = true;
Q.push(block(1, 1, 0, 0));
while(!Q.empty()){
block b = Q.front(); Q.pop();
int x = b.x, y = b.y, step = b.step, state = b.state;
if(x == n && y == n)
return step;
for(int i = 0; i < 4; ++i){
int newx = x + dirs[i][0], newy = y + dirs[i][1];
if(newx < 1 || newx > n || newy < 1 || newy > n)
continue;
if(maze[newx][newy] == '#')
continue;
else if(!vis[newx][newy]){
if(maze[newx][newy] == '.'){
if(state)
Q.push(block(newx, newy, step + 1, state - 1));
else
Q.push(block(newx, newy, step + 1, 0));
vis[newx][newy] = true;
}
else if(maze[newx][newy] == 'X'){
if(state){
Q.push(block(newx, newy, step + 1, state - 1));
vis[newx][newy] = true;
}
}
else{
Q.push(block(newx, newy, step + 1, k));
vis[newx][newy] = true;
}
}
else if((maze[newx][newy] == '.' || maze[newx][newy] == 'X') && state){
Q.push(block(newx, newy, step + 1, state - 1));
}
}
}
return -1;
}
int main(){
int n, k;
scanf("%d%d", &n, &k);
for(int i = 1; i <= n; ++i){
scanf("%s", maze[i] + 1);
}
printf("%d\n", BFS(n, k));
return 0;
}
Python 超时,C++ 秒过。Python 果然还是太慢了。