P2895 [USACO08FEB]Meteor Shower S 题解

题目传送门

感悟与理解

1、

#include <bits/stdc++.h>

using namespace std;
const int INF = 0x3f3f3f3f;
const int N = 310;

//二维坐标系中每个点的上下左右变化delta坐标
int dx[4] = {0, 0, -1, 1};
int dy[4] = {1, -1, 0, 0};

int a[N][N];           //x,y坐标的最早被流星覆盖到的时间
bool st[N][N];         //x,y坐标是不是已经走过,防止走回头路

//定义结构体,x,y这个坐标,到达需要step步骤
struct coord {
    int x, y;
    int step;
};

//广度优先搜索
int bfs() {
    queue<coord> q;

    //出发的原点位置
    q.push({0, 0, 0});
    //标识走过了
    st[0][0] = true;

    //广度优先搜索的框架
    while (!q.empty()) {
        //队列首
        coord u = q.front();
        //出队列
        q.pop();
        //四个方向
        for (int i = 0; i < 4; i++) {
            int nx = u.x + dx[i];
            int ny = u.y + dy[i];
            //出了第一象限是不可以的
            if (nx < 0 || ny < 0)continue;

            //多走一步啊
            int step = u.step + 1;
            //如果这个点为INF,表示永远不会被摧毁,已经安全了
            if (a[nx][ny] == INF)return step;

            //如果到达这个时间点的时间早于最早摧毁时间,可以走
            if (step < a[nx][ny] && !st[nx][ny]) {
                st[nx][ny] = true;
                q.push({nx, ny, step});
            }
        }
    }
    return -1;
}

int main() {
    //初始化为INF(预求最小,先设最大)
    memset(a, 0x3f, sizeof a);

    //一共m个流星
    int m;
    cin >> m;
    for (int i = 1; i <= m; i++) {
        int x, y, t;
        cin >> x >> y >> t;

        //预处理的过程
        //Q:预处理的是什么?
        //A:每个点,都有一个最早的破坏时间,可能是直接被砸中,也可能是被牵连~,那么,这个点,是什么时间被一次覆盖到呢?需要预处理出来
        //求出该点和周围点的最早摧毁时间
        a[x][y] = min(a[x][y], t); //如果直接砸中的时间小于原来记录的时间,需要修改一下。
        for (int j = 0; j < 4; j++) {
            //可以到达的新坐标位置
            int nx = x + dx[j];
            int ny = y + dy[j];
            //一直在第一象限行动,只要nx,ny不小于0,可以随意向右,向上去走,右和上没有边界
            if (nx >= 0 && ny >= 0) a[nx][ny] = min(a[nx][ny], t);
        }
    }
    //广度优先搜索
    printf("%d\n", bfs());
    return 0;
}
上一篇:P2894 [USACO08FEB]Hotel G


下一篇:P2894 [USACO08FEB] Hotel G