题目
思路
首先,整体的思路是,小蓝如果起始的能量值够用的话,可以从起点到终点直接最短路径,如果不够的话,肯定是要先经过圣泉并停留一定的时间(这要由能量剩余值和圣泉到终点的路径长度决定),如果是不止一个圣泉,我们要遍历所有圣泉,找到最短路径和。
题目给的是一个二维矩阵,每个点可达的地方,就相当于是与它有一条可以连的无向边,然后在无向图中确定最短路径就是广搜BFS,每一轮遍历所有可以到达的结点。
要解决这个题,我们得知道:小蓝到终点的最短距离,小蓝到圣泉的最短距离,圣泉到终点的距离。
所以是两次BFS,第一次得到起点到任意点的最短距离,(如果那个点是不可达的点,就设为-1)。第二次是找到圣泉到终点最短距离。
代码
#include <iostream>
#include <cstring>
#include <algorithm>
#include <queue>
#define x first
#define y second
using namespace std;
typedef pair<int, int> PII;
const int N = 1e3 + 10;
int dx[4] = {-1, 0, 1, 0}, dy[4] = {0, 1, 0, -1};
int n, m, E;
int A, B, C, D;
char g[N][N];
vector<vector<int>> dist1, dist2;
void bfs(int x, int y, vector<vector<int>> &dist)
{
dist[x][y] = 0;
queue<PII> q;
q.push({x, y});
while (q.size())
{
auto t = q.front();
q.pop();
for (int i = 0; i < 4; ++ i )
{
int tx = t.x + dx[i], ty = t.y + dy[i];
if (tx < 0 || ty < 0 || tx >= n || ty >= m || g[tx][ty] == '#')
continue;
if (dist[tx][ty] <= dist[t.x][t.y] + 1)
continue;
dist[tx][ty] = dist[t.x][t.y] + 1;
q.push({tx, ty});
}
}
}
int main()
{
cin >> n >> m;
cin >> A >> B >> C >> D;
A --, B --, C --, D --;
for (int i = 0; i < n; ++ i )
cin >> g[i];
cin >> E;
dist1 = vector<vector<int>>(n, vector<int>(m, 0x3f3f3f3f));
dist2 = vector<vector<int>>(n, vector<int>(m, 0x3f3f3f3f));
bfs(A, B, dist1);
bfs(C, D, dist2);
int res = dist1[C][D];
if (res <= E)
{
cout << res << endl;
return 0;
}
res = 0x3f3f3f3f;
for (int i = 0; i < n; ++ i )
for (int j = 0; j < m; ++ j )
if (g[i][j] == 'V')
if (dist1[i][j] <= E)
res = min(res, dist1[i][j] + dist2[i][j]);
if (res != 0x3f3f3f3f)
cout << (res - E) * 2 + E << endl;
else
puts("No");
return 0;
}