P2895 [USACO08FEB] Meteor Shower S 时限BFS

解题思路

这道题是一个典型的带时间限制的BFS问题,需要考虑流星坠落时间对路径选择的影响。关键点在于:

  1. 地图预处理:首先计算每个格子最早被流星摧毁的时间

  2. 安全区域判断:安全区域是指永远不会被流星摧毁的格子(即g[x][y] = ∞)

  3. BFS扩展条件:贝茜只能在到达某格子的时间早于该格子被摧毁的时间才能移动

  4. 边界处理:注意坐标不能为负值

代码注释

#include<bits/stdc++.h>
using namespace std;

const int N = 3e2 + 10;  // 定义地图最大尺寸
const int inf = 0x3f3f3f3f;  // 定义无穷大值

// 定义节点结构体,存储坐标和步数
struct node {
    int x, y, step;  // x,y是坐标,step是到达该点的步数
};

int g[N][N];     // 存储每个格子最早被摧毁的时间
int vis[N][N];   // 访问标记数组
int nex[4][2] = {{0,1}, {1,0}, {0,-1}, {-1,0}};  // 四个移动方向:右、下、左、上
int m;           // 流星数量

// BFS函数,从起点(sx,sy)开始搜索
void bfs(int sx, int sy) {
    queue<node> q;       // 创建队列用于BFS
    vis[sx][sy] = 1;     // 标记起点已访问
    q.push({sx, sy, 0}); // 起点入队,初始步数为0
    
    while(q.size()) {    // 当队列不为空时循环
        node h = q.front(); q.pop(); // 取出队首元素
        
        // 尝试四个方向移动
        for(int i = 0; i < 4; i++) {
            int tx = h.x + nex[i][0];  // 计算新坐标x
            int ty = h.y + nex[i][1];  // 计算新坐标y
            
            // 边界检查:坐标不能为负
            if(tx < 0 || ty < 0) continue;
            
            // 检查移动时间是否早于被摧毁时间且未访问过
            if(h.step + 1 >= g[tx][ty] || vis[tx][ty]) continue;
            
            vis[tx][ty] = 1;  // 标记为已访问
            q.push({tx, ty, h.step + 1});  // 新位置入队,步数+1
            
            // 如果到达安全区域(永远不会被摧毁的格子)
            if(g[tx][ty] == inf) {
                cout << h.step + 1;  // 输出当前步数
                return;              // 直接返回
            }
        }
    }
    
    // 如果队列为空仍未找到安全区域,输出-1
    cout << "-1";
}

int main() {
    // 初始化所有格子为无穷大(表示初始都是安全的)
    memset(g, 0x3f3f3f3f, sizeof(g));
    
    // 读取流星数量
    cin >> m;
    
    // 处理每个流星
    for(int i = 1; i <= m; i++) {
        int x, y, z;
        cin >> x >> y >> z;  // 读取流星坐标和坠落时间
        
        // 更新流星撞击点最早被摧毁时间
        g[x][y] = min(g[x][y], z);
        
        // 更新流星影响的周围4个格子
        for(int k = 0; k < 4; k++) {
            int tx = x + nex[k][0], ty = y + nex[k][1];
            if(tx < 0 || ty < 0) continue;  // 边界检查
            g[tx][ty] = min(g[tx][ty], z);  // 更新最早被摧毁时间
        }
    }
    
    // 执行BFS搜索,从原点(0,0)开始
    bfs(0, 0);
    
    return 0;
}

 

posted @ 2025-06-06 15:02  CRt0729  阅读(16)  评论(0)    收藏  举报