题意:
个格子组成的迷宫,迷宫中有陷阱 '#',和可通行的点 '.',起点为 'S',终点为 'T'。
每次移动代价为 1。
另有传送阵若干,可以从传送阵的入口传送至出口,代价为 3。
问从起点移动到终点的最小代价。
解法:
不考虑传送阵,最裸的 BFS。
考虑传送阵,也算是比较经典的模型。
有两种解法,但本质思想是一样。
一种是建图,迷宫中的每一个格子视作一个顶点,上下左右相邻的格子间建一条权值为 1 的双向边。
传送阵的入口和出口之间建一条权值为 3 的单向边。
然后跑个最短路 dijstra 就行了。
另一种是堆优化的 BFS,实现也和 dijkstra 很类似。只不过不用重新建图。
代码实现的就是这种方式。
Code:
#include <bits/stdc++.h> using namespace std; using pii = pair<int, int>; const int N = 300 + 5; const int dx[] = {-1, 0, 0, 1}, dy[] = {0, -1, 1, 0}; struct Node { int val, x, y; Node() { } Node(int _val, int _x, int _y): val(_val), x(_x), y(_y) { } bool operator < (const Node &t) const { return val > t.val; } }; char maze[N][N]; int n, m, q; vector<pii> a[N][N]; int sx, sy, ex, ey, step[N][N]; int main() { while(cin >> n >> m >> q) { for(int i = 1; i <= n; i++) for(int j = 1; j <= m; j++) { cin >> maze[i][j]; if(maze[i][j] == 'S') sx = i, sy = j; if(maze[i][j] == 'T') ex = i, ey = j; a[i][j].clear(); step[i][j] = 0x3f3f3f3f; } for(int i = 1; i <= q; i++) { int x1, y1, x2, y2; cin >> x1 >> y1 >> x2 >> y2; x1++, y1++, x2++, y2++; a[x1][y1].push_back({x2, y2}); } step[sx][sy] = 0; priority_queue<Node> q; q.push(Node(0, sx, sy)); while(!q.empty()) { int val = q.top().val, x = q.top().x, y = q.top().y; q.pop(); if(step[x][y] < val) continue; for(int i = 0; i < 4; i++) { int nx = x + dx[i], ny = y + dy[i]; if(1 <= nx && nx <= n && 1 <= ny && ny <= m && maze[nx][ny] != '#' && step[nx][ny] > step[x][y] + 1) { step[nx][ny] = step[x][y] + 1; q.push(Node(step[nx][ny], nx, ny)); } } for(pii e : a[x][y]) { int nx = e.first, ny = e.second; if(1 <= nx && nx <= n && 1 <= ny && ny <= m && maze[nx][ny] != '#' && step[nx][ny] > step[x][y] + 3) { step[nx][ny] = step[x][y] + 3; q.push(Node(step[nx][ny], nx, ny)); } } } int ans = step[ex][ey]; if(ans == 0x3f3f3f3f) ans = -1; cout << ans << endl; } }