思路
- 显然是图论问题,而看到最短距离就应该优先使用BFS。
- 先后用BFS计算人和猫到其各自范围中任意合法位置的最短距离。注意处于人移动范围的合法位置会由于障碍物'*'的阻碍无法到达,而猫的嗅觉范围可以无视障碍物到达,这一点在BFS的代码中是否将新位置加入队列中的判断条件上有所体现。
- 最后遍历两者都能到达的合法位置选出距离和最短解。
代码实习
#include <bits/stdc++.h>
using namespace std;
using ll = long long;
char g[1000][1000];
int d1[1000][1000];
int d2[1000][1000];
int dx[4] = {1, -1, 0, 0};
int dy[4] = {0, 0, 1, -1};
pair<int, int> P, M;
int n, m;
int r1, r2;
bool visited2[1000][1000];
bool visited1[1000][1000];
void bfs1()
{
queue<pair<int, int>> q;
q.push(P);
visited1[P.first][P.second] = true;
int cnt = 0;
while (!q.empty())
{
pair<int, int> t = q.front();
q.pop();
for (int i = 0; i < 4; i++)
{
int x = t.first + dx[i];
int y = t.second + dy[i];
if (x >= 0 && x < n && y >= 0 && y < m && !visited1[x][y] &&
g[x][y] != '*' && abs(x - P.first) + abs(y - P.second) <= r1)
{
q.push({x, y});
visited1[x][y] = true;
d1[x][y] = d1[t.first][t.second] + 1;
}
}
}
}
void bfs2()
{
queue<pair<int, int>> q;
q.push(M);
visited2[M.first][M.second] = true;
int cnt = 0;
while (!q.empty())
{
pair<int, int> t = q.front();
q.pop();
for (int i = 0; i < 4; i++)
{
int x = t.first + dx[i];
int y = t.second + dy[i];
if (x >= 0 && x < n && y >= 0 && y < m && !visited2[x][y] && g[x][y] != '*')
{
q.push({x, y});
visited2[x][y] = true;
d2[x][y] = d2[t.first][t.second] + 1;
}
}
}
}
int main()
{
ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);
cin >> n >> m;
cin >> r1 >> r2;
for (int i = 0; i < n; i++)
{
for (int j = 0; j < m; j++)
{
cin >> g[i][j];
if (g[i][j] == 'P')
{
P.first = i;
P.second = j;
}
else if (g[i][j] == 'M')
{
M.first = i;
M.second = j;
}
}
}
bfs1();
bfs2();
int ans = 0x3f3f3f3f;
for (int i = 0; i < n; i++)
{
for (int j = 0; j < m; j++)
{
if (d1[i][j] && d2[i][j] && abs(i - M.first) + abs(j - M.second) <= r2)
{
ans = min(ans, d1[i][j] + d2[i][j]);
}
}
}
if (ans == 0x3f3f3f3f)
{
cout << -1;
}
else
{
cout << ans;
}
return 0;
}