KSzsh

导航

游戏购买!(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;
}

posted on 2022-11-15 20:42  KSzh  阅读(34)  评论(0编辑  收藏  举报