【C++算法】87.BFS解决最短路径问题_为高尔夫比赛砍树

发布于:2025-07-31 ⋅ 阅读:(20) ⋅ 点赞:(0)


题目链接:

675. 为高尔夫比赛砍树


题目描述:

0339fa60c45511642b1d5d83f27bd81f


解法

注意:砍树要从低到高砍。

砍掉1,从1到5到2

砍掉2,从2到5到3

砍掉3,从3到5到2到6到4

砍掉4,从4到6到5

砍掉5,从5到6

砍掉6

4e11a26528f702773cd0fa1559e658b7

变成若干个迷宫问题了。

把所有的最小值求出来然后加起来。

3fc2f78c65c913da061063fc9ac8c177

但是有个问题,你怎么知道砍树的顺序呢?

所以我们要先找到砍树的顺序,弄个二维数组先存一下下标和内容,然后按照内容由小到大排序。


C++ 算法代码:

class Solution {
    int m, n;  // 森林的行数和列数

public:
    int cutOffTree(vector<vector<int>>& f) {
        m = f.size(), n = f[0].size();
        // 1. 准备工作:找出所有需要砍的树,并按树的高度排序
        vector<pair<int, int>> trees;
        for (int i = 0; i < m; i++)
            for (int j = 0; j < n; j++)
                if (f[i][j] > 1)  // 树的高度大于1才需要砍
                    trees.push_back({i, j});

        // 按照树的高度从小到大排序
        sort(trees.begin(), trees.end(),
             [&](const pair<int, int>& p1, const pair<int, int>& p2) {
                 return f[p1.first][p1.second] < f[p2.first][p2.second];
             });
        
        // 2. 按照顺序砍树
        int bx = 0, by = 0;  // 起始位置(0,0)
        int ret = 0;  // 总步数
        for (auto& [a, b] : trees) {
            // 计算从当前位置到下一棵树的最短步数
            int step = bfs(f, bx, by, a, b);
            if (step == -1)  // 如果无法到达,返回-1
                return -1;
            ret += step;  // 累加步数
            bx = a, by = b;  // 更新当前位置
        }
        return ret;
    }

    bool vis[51][51];  // 访问标记数组
    int dx[4] = {0, 0, 1, -1};  // 四个方向的x偏移量
    int dy[4] = {1, -1, 0, 0};  // 四个方向的y偏移量
    
    // BFS计算从起点(bx,by)到终点(ex,ey)的最短步数
    int bfs(vector<vector<int>>& f, int bx, int by, int ex, int ey) {
        if (bx == ex && by == ey)  // 如果起点就是终点,返回0步
            return 0;
            
        queue<pair<int, int>> q;
        memset(vis, 0, sizeof vis);  // 清空访问标记
        q.push({bx, by});
        vis[bx][by] = true;
        int step = 0;
        
        while (q.size()) {
            step++;
            int sz = q.size();
            // 处理当前层的所有节点
            while (sz--) {
                auto [a, b] = q.front();
                q.pop();
                // 尝试四个方向
                for (int i = 0; i < 4; i++) {
                    int x = a + dx[i], y = b + dy[i];
                    // 检查新位置是否合法
                    if (x >= 0 && x < m && y >= 0 && y < n && 
                        f[x][y] != 0 && !vis[x][y]) {  // 0表示不能走的障碍物
                        // 找到终点,返回当前步数
                        if (x == ex && y == ey)
                            return step;
                        q.push({x, y});
                        vis[x][y] = true;
                    }
                }
            }
        }
        return -1;  // 无法到达终点
    }
};

网站公告

今日签到

点亮在社区的每一天
去签到