题意:
个格子组成的迷宫,迷宫中有陷阱 '#',和可通行的点 '.',起点为 '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;
}
} 
京公网安备 11010502036488号