bfs
题意
小明来到一个由n x m个格子组成的迷宫,有些格子是陷阱,用'#'表示,小明进入陷阱就会死亡,'.'表示没有陷阱。小明所在的位置用'S'表示,目的地用'T'表示。
小明只能向上下左右相邻的格子移动,每移动一次花费1秒。
有q个单向传送阵,每个传送阵各有一个入口和一个出口,入口和出口都在迷宫的格子里,当走到或被传送到一个有传送阵入口的格子时,小明可以选择是否开启传送阵。如果开启传送阵,小明就会被传送到出口对应的格子里,这个过程会花费3秒;如果不开启传送阵,将不会发生任何事情,小明可以继续向上下左右四个方向移动。
一个格子可能既有多个入口,又有多个出口,小明可以选择任意一个入口开启传送阵。使用传送阵是非常危险的,因为有的传送阵的出口在陷阱里,如果小明使用这样的传送阵,那他就会死亡。也有一些传送阵的入口在陷阱里,这样的传送阵是没有用的,因为小明不能活着进入。请告诉小明活着到达目的地的最短时间。
分析
如果没上雨神的课,这道题我会做的够呛。关键是对bfs的理解。
如课上所说的,我们使用bfs标记每一个到达每一个方块的最短时间。如果,我们遍历到这个方块,而我们现在到这个方块的时间大于等于这个方块上所标记的时间,那我们便应该忽视该方块!不放在队列中,也不进行改动。
这样bfs一下来,每一个方块上都标记了,我们到他的最短时间。不能到达的为初始的INF。
代码如下、注意细节
#include<iostream> #include<algorithm> #include<deque> using namespace std; const int max_n = 350; const int max_q = 1500; const int INF = 1e9; int vis[max_n * max_n]; int ans[max_n * max_n]; int n, m, q; int start, End; int bfs() { int p1, p2, p3, p4; deque<int> que;ans[start] = 0; que.push_back(start); while (!que.empty()) { int cur = que.front();que.pop_front(); p1 = cur - 1;p2 = cur + 1; p3 = cur - m;p4 = cur + m; if (cur % m != 0 && vis[p1]) { if (ans[p1] > ans[cur] + 1) { ans[p1] = ans[cur] + 1; que.push_back(p1); } } if (p2 % m != 0 && vis[p2]) { if (ans[p2] > ans[cur] + 1) { ans[p2] = ans[cur] + 1; que.push_back(p2); } } if (p3 >= 0 && vis[p3]) { if (ans[p3]> ans[cur] + 1) { ans[p3] = ans[cur] + 1; que.push_back(p3); } } if (p4 < m*n && vis[p4]) { if (ans[p4] > ans[cur] + 1) { ans[p4] = ans[cur] + 1; que.push_back(p4); } } if (vis[cur] > INF) { int p5 = vis[cur] - INF; if (ans[p5] > ans[cur] + 3) { ans[p5] = ans[cur] + 3; que.push_back(p5); } } } if (ans[End] == INF)return -1; return ans[End]; } int main() { ios::sync_with_stdio(0); while (cin >> n >> m >> q) { char ch;fill(vis, vis + max_n * max_n, 2); fill(ans, ans + max_n * max_n, INF); for (int i = 0;i < n;i++) { for (int j = 0;j < m;j++) { cin >> ch; if (ch == 'S')start = i * m + j; else if (ch == '#')vis[i * m + j] = 0; else if (ch == 'T')End = i * m + j; } }int x1, y1, x2, y2; for (int i = 0;i < q;i++) { cin >> x1 >> y1 >> x2 >> y2; if (!vis[x1 * m + y1] || !vis[x2 * m + y2])continue; vis[x1 * m + y1] = INF + x2 * m + y2; } cout << bfs() << endl; } }