游戏购买!(bfs问题)
题目描述:
小竹成功从家里逃了出来,他决定去小胖家避一避。但是小胖要求小竹带一个刺激度大于 \(x\) 的游戏才能去他家。
为了防止被妈妈或她的朋友发现,小竹不会在道路上行走,而是在建筑物与建筑物之间穿行。
街道表现为一个 \(n×m\) 的网格,网格上只有两种建筑: 商店和住宅。商店可以通过而住宅无法通过。
小竹每次从当前所在网格可以行走到上下左右的网格中,但不能移动到网格的边界之外和别人的家中。正式的说,如果他在坐标为 \((i,j)\) 的网格里,他可以选择 \((i+1,j), (i - 1,j), (i,j+1), (i,j−1)\) 四个方向行走。
在位置 \((i,j)\) 上的商店有一个刺激度为 \(w_{i,j}\)的游戏,小竹可以购买他所经过的商店中的游戏并带走。若 \(w_{i,j}\)为 \(-1\) 则代表这个位置是个住宅,无法通过。
注意:小胖家以及小竹家均可以被通过。
假设相邻的建筑物的距离均为 \(1\),小竹想知道带一个刺激度高于 \(x\) 的游戏去小胖家需要的最短距离是多少?如果这是不可能实现的,请输出 \(-1\)。
输入描述:
第一行三个整数 \(n,m,x(1\le n,m \le 2000,1\le x \le 10^9)\)
第二行四个整数\(sx,sy,ex,ey(1≤sx,ex≤n,1≤sy,ey≤m)\)表示起点与终点的坐标,\(w_{sx,sy} ,w_{ex,ey}\)均为\(0\)。
接下来 \(n\) 行,每行 \(m\) 个整数,第 \(i\) 行第 \(j\) 个整数 \(w_{i,j}(-1\le w_{i,j} \le 10^9)\),其中所有商店的\(w_{i,j} \geq 1。\)
输出描述:
一行一个整数,表示最短距离,若无法携带一个刺激度大于 \(x\) 的游戏到小胖家,输出\(-1\)。
题解:
#include <bits/stdc++.h>
using namespace std;
typedef pair<int, int> PII;
const int N = 2010;
int sx, sy, ex, ey;
int n, m, x;
int a[N][N];
int d1[N][N]; // d1 代表起点到任何点的距离
int d2[N][N]; // d2 代表终点到任何点的距离
int dx[4] = {1, -1, 0, 0}, dy[4] = {0, 0, 1, -1}; // 上下左右四个方向
bool st[N][N]; // st 代表每个点是否被遍历到
vector<PII> v; // 用来存储商店的坐标
void bfs(int d[N][N], int x, int y)
{
queue<PII> q;
q.push({x, y});
memset(st, 0, sizeof st);
st[x][y] = 1;
d[x][y] = 0;
while (q.size())
{
auto t = q.front();
q.pop();
for (int i = 0; i < 4; i++)
{
int tx = t.first + dx[i];
int ty = t.second + dy[i];
if (tx >= 1 && tx <= n && ty >= 1 && ty <= m && st[tx][ty] == 0 && a[tx][ty] != -1)
{
q.push({tx, ty});
d[tx][ty] = d[t.first][t.second] + 1;
st[tx][ty] = 1;
}
}
}
}
int main()
{
ios::sync_with_stdio(false), cin.tie(0), cout.tie(0);
cin >> n >> m >> x;
cin >> sx >> sy >> ex >> ey;
memset(d1, 0x3f, sizeof d1); // 因为要求最小值,所以将距离初始化为正无穷
memset(d2, 0x3f, sizeof d2); // 因为可能会有到不了的情况
for (int i = 1; i <= n; i++)
{
for (int j = 1; j <= m; j++)
{
cin >> a[i][j];
if (a[i][j] > x)
{
v.push_back({i, j}); // 将游戏刺激度大于 x 的商店存入 v
}
}
}
bfs(d1, sx, sy); // 进行两遍 bfs
bfs(d2, ex, ey);
int res = 0x3f3f3f3f;
for (auto j : v)
{
res = min(res, d1[j.first][j.second] + d2[j.first][j.second]); // 找寻从起点到商店和从商店到终点的距离的最小值
}
if (res == 0x3f3f3f3f)
printf("-1");
else
printf("%d", res);
return 0;
}