题解 | #maze#
maze
https://ac.nowcoder.com/acm/problem/15665
maze
思路
- 将每个点上的入口到对应出口也看成一条路径, 只不过从这条路径走距离一次+3
- 然后就是普通的bfs,注意队列要使用优先队列, 因为此时的队列不再具备步数的单调性,需要人为保证步数单调性。优先队列元素定义如下,注意优先队列的重载,可以参考《算法笔记》P223
struct Node
{
int x, y;
int step;
bool operator<(const Node &w) const
{
return step > w.step; // bfs的队列优先级: 步数小的优先
}
};
priority_queue<Node> pq;
代码
#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
typedef pair<int, int> PII;
typedef pair<double, double> PDD;
int dx[] = {-1, 1, 0, 0}, dy[] = {0, 0, -1, 1};
const double eps = 1e-6;
const int N = 300 + 10;
int n, m, q;
char g[N][N];
PII start, ed;
vector<PII> v[N][N]; // v[i][j]中存储点(i,j)能通过传送直接到达的点
bool st[N][N];
struct Node
{
int x, y;
int step;
bool operator<(const Node &w) const
{
return step > w.step; // bfs的队列优先级: 步数小的优先
}
};
priority_queue<Node> pq;
int bfs()
{
memset(st, 0, sizeof st);
while (pq.size())
pq.pop();
pq.push({start.first, start.second, 0});
st[start.first][start.second] = true;
while (!pq.empty())
{
Node t = pq.top();
pq.pop();
if (t.x == ed.first && t.y == ed.second)
return t.step;
for (PII i : v[t.x][t.y])
{
int a = i.first, b = i.second;
if (g[a][b] != '#')
pq.push({a, b, t.step + 3});
}
for (int i = 0; i < 4; i++)
{
int a = t.x + dx[i], b = t.y + dy[i];
if (a < 0 || a > n - 1 || b < 0 || b > m - 1)
continue;
if (st[a][b])
continue;
if (g[a][b] == '#')
continue;
st[a][b] = true;
pq.push({a, b, t.step + 1});
}
}
return -1;
}
int main()
{
ios::sync_with_stdio(false);
cin.tie(0);
while (cin >> n >> m >> q)
{
for (int i = 0; i < n; i++)
{
cin >> g[i];
}
for (int i = 0; i < n; i++)
{
for (int j = 0; j < m; j++)
{
if (g[i][j] == 'S')
start.first = i, start.second = j;
if (g[i][j] == 'T')
ed.first = i, ed.second = j;
v[i][j].clear();
}
}
while (q--)
{
int x1, y1, x2, y2;
cin >> x1 >> y1 >> x2 >> y2;
v[x1][y1].push_back({x2, y2});
}
cout << bfs() << '\n';
}
return 0;
}