P8673 [蓝桥杯 2018 国 C] 迷宫与陷阱 题解
这题是普通 bfs 的变形题。加了一个道具的操作。
板子相信大家都会敲,那么主要讲一下如何处理无敌道具。
在结构体内新加一个变量
这里要加一个剪枝:加一个 int 型的数组 vis[x][y] < magic,即如果当前节点已经被访问过,且之前到达该节点时的无敌状态剩余步数比现在要多,则不需要再次访问该节点。因为如果我们之前已经访问过该节点并且使用了更多的无敌步数,那么这条路径一定不是最优解。初始时要赋值为全
代码+详细注释:
#include <bits/stdc++.h>
using namespace std;
const int N = 1e3 + 5;
int n, k;
char g[N][N];
int vis[N][N]; // 存储每个格子是否被访问过以及无敌状态剩余步数
struct node{
int x, y, step, magic;
};
int dx[4] = {1, -1, 0, 0};
int dy[4] = {0, 0, 1, -1};
int main(){
cin >> n >> k;
for (int i = 1; i <= n; i ++ )
for (int j = 1; j <= n; j ++ )
cin >> g[i][j];
memset(vis, -1, sizeof vis);
queue<node> q;
vis[1][1] = 0; // 将起点的访问状态设置为0
q.push({1, 1, 0, 0}); // 将起点入队,并设置其到达该点的步数为0、当前不处于无敌状态
while (q.size()){
node t = q.front(); // 取出队头节点
q.pop();
if (t.x == n && t.y == n){ // 如果当前节点为终点,则输出最短路长度并结束程序
cout << t.step;
return 0;
}
for (int i = 0; i < 4; i ++ ){
int tx = t.x + dx[i];
int ty = t.y + dy[i];
if (g[tx][ty] == 'X' && t.magic == 0) // 如果下一步位置是陷阱且当前不处于无敌状态,则跳过该节点
continue;
int magic = max(0, t.magic - 1); // 计算当前无敌状态剩余步数
if (g[tx][ty] == '%') // 如果下一步位置有道具,更新无敌状态剩余步数
magic = k;
if (tx >= 1 && tx <= n && ty >= 1 && ty <= n && vis[tx][ty] < magic && g[tx][ty] != '#'){ // 如果下一步位置是合法的可到达位置
vis[tx][ty] = magic; // 更新访问状态和无敌状态剩余步数
q.push({tx, ty, t.step + 1, magic}); // 将下一步位置入队,并更新到达该点的步数和无敌状态剩余步数
}
}
}
cout << -1;
return 0;
}