1 条题解

  • 0
    @ 2026-2-17 23:02:58
    #include<bits/stdc++.h>
    using namespace std;
    
    // 棋盘最大尺寸,适配n,m≤1000的要求
    const int MAXN = 1005;
    // 四个移动方向:上、下、左、右
    int dx[] = {-1, 1, 0, 0};
    int dy[] = {0, 0, -1, 1};
    
    int a[MAXN][MAXN];   // 存储每个房间的伤害值
    int vis[MAXN][MAXN]; // 访问标记数组,用时间戳避免每次重置
    int tim = 0;         // 时间戳,用于标记当前BFS的访问状态
    int n, m;            // 迷阵的行数n、列数m
    
    // 验证函数:判断伤害上限为mid时,是否存在可行路径
    bool check(int mid)
    {
        tim++; // 时间戳+1,区分不同次BFS的访问标记
        queue<pair<int, int>> q;
    
        // 多源BFS初始化:第一行所有入口都作为起点入队
        for(int j = 1; j <= m; j++)
        {
            if(a[1][j] <= mid) // 第一行伤害为0,必然满足条件
            {
                vis[1][j] = tim;
                q.push({1, j});
            }
        }
    
        // BFS核心循环
        while(!q.empty())
        {
            auto [x, y] = q.front();
            q.pop();
    
            // 到达第n行,直接返回可行
            if(x == n)
            {
                return true;
            }
    
            // 遍历四个移动方向
            for(int i = 0; i < 4; i++)
            {
                int nx = x + dx[i];
                int ny = y + dy[i];
                // 合法性校验:
                // 1. 坐标在迷阵范围内
                // 2. 该格子未被当前BFS访问过
                // 3. 该格子的伤害值≤当前上限mid
                if(nx >= 1 && nx <= n && ny >= 1 && ny <= m && vis[nx][ny] != tim && a[nx][ny] <= mid)
                {
                    vis[nx][ny] = tim;
                    q.push({nx, ny});
                    // 提前判断:到达第n行直接返回,无需继续遍历
                    if(nx == n)
                    {
                        return true;
                    }
                }
            }
        }
    
        // 遍历完所有可达格子仍未到达第n行,不可行
        return false;
    }
    
    int main()
    {
        // 关闭cin同步,加速输入输出
        ios::sync_with_stdio(false);
        cin.tie(nullptr);
    
        // 读取迷阵大小
        cin >> n >> m;
        // 读取每个房间的伤害值,使用1-based坐标和题目对应
        for(int i = 1; i <= n; i++)
        {
            for(int j = 1; j <= m; j++)
            {
                cin >> a[i][j];
            }
        }
    
        // 二分答案核心循环
        int left = 0, right = 1000; // 伤害值最大为1000,右边界设为1000
        int ans = 1000;              // 记录最终答案
        while(left <= right)
        {
            int mid = (left + right) / 2;
            if(check(mid))
            {
                // 当前mid可行,尝试寻找更小的可行值
                ans = mid;
                right = mid - 1;
            }
            else
            {
                // 当前mid不可行,需要增大上限
                left = mid + 1;
            }
        }
    
        // 输出最小伤害代价
        cout << ans << '\n';
    
        return 0;
    }
    
    • 1

    信息

    ID
    1304
    时间
    1000ms
    内存
    256MiB
    难度
    3
    标签
    递交数
    1
    已通过
    1
    上传者