LintCode1092: Cut Off Trees for Golf Event (经典BFS题!)

本文探讨了一种基于BFS算法的森林砍树路径规划问题,旨在为高尔夫赛事清理场地。通过将树木按高度排序并寻找从一棵树到下一棵树的最短路径,实现了从起点到所有树的最小步数计算。
  1. Cut Off Trees for Golf Event
    You are asked to cut off trees in a forest for a golf event. The forest is represented as a non-negative 2D map, in this map:

0 represents the obstacle can’t be reached.
1 represents the ground can be walked through.
The place with number bigger than 1 represents a tree can be walked through, and this positive number represents the tree’s height.
You are asked to cut off all the trees in this forest in the order of tree’s height - always cut off the tree with lowest height first. And after cutting, the original place has the tree will become a grass (value 1).
You will start from the point (0, 0) and you should output the minimum steps you need to walk to cut off all the trees. If you can’t cut off all the trees, output -1 in that situation.

You are guaranteed that no two trees have the same height and there is at least one tree needs to be cut off.

Example
Input:
[
[1,2,3],
[0,0,4],
[7,6,5]
]
Output: 6

Input:
[
[1,2,3],
[0,0,0],
[7,6,5]
]
Output: -1

Input:
[
[2,3,4],
[0,0,5],
[8,7,6]
]
Output: 6
Explanation: You started from the point (0,0) and you can cut off the tree in (0,0) directly without walking.

Notice
size of the given matrix will not exceed 50x50.

这题类似骑士遍历题,也是基于BFS,但稍复杂一些。
思路:

  1. 将trees按低到高排序。
  2. 按trees从低到高,每次用BFS找到从ith高的树到i+1th高的树的最短路径。返回所有最短路径之和即可。
  3. 因为每次都要重新调用BFS,所以每次visited map都要初始化。
  4. 砍完某树后应该将其高度设为1。
    代码如下:
struct Node {
    int row;
    int col;
    int height;
    Node(int x, int y, int z) : row(x), col(y), height(z) {}
    bool operator < (const Node & node) const {
        return height < node.height;
    }
};

class Solution {
public:
    /**
     * @param forest: a list of integers
     * @return: return a integer
     */
    int cutOffTree(vector<vector<int>> &forest) {
        if (forest.size() == 0) return 0;
        int lenR = forest.size();
        int lenC = forest[0].size();
        vector<Node> trees;
        
        for (int i = 0; i < lenR; ++i) {
            for (int j = 0; j < lenC; ++j) {
                int val = forest[i][j];
                if ((val != 0) && (val != 1))
                    trees.push_back(Node(i, j, val));
            }
        }
        
        sort(trees.begin(), trees.end());
        int len = trees.size() - 1; // one less than the trees size
        int result = 0;
        
        Node node0 = Node(0, 0, forest[0][0]);
        
        result += bfs(forest, node0, trees[0]);
        for (int i = 0; i < len; ++i) {
            int steps = bfs(forest, trees[i], trees[i + 1]);
            if (steps == -1) 
                return -1;
            else 
                result += steps;      
        }
        
        return result;
    }

private:
    int bfs(vector<vector<int>> &forest, Node &src, Node &dest) {
        //down, left, up, right
        vector<int> dirR = {1, 0, -1, 0}; //col 
        vector<int> dirC = {0, -1, 0, 1}; //row 
        
        //each time of bfs, the visited map needs reset
        vector<vector<int>> visited(forest.size(), vector<int>(forest[0].size(), 0));
        
        queue<Node> q;
        q.push(src);
        
        int steps = 0;
        while(!q.empty()) {
            int qSize = q.size();
            for (int i = 0; i < qSize; ++i) {
                Node n = q.front();
                q.pop();

                if ((n.row == dest.row) && (n.col == dest.col)) {
                    forest[dest.row][dest.col] = 1; //after the tree is cut, set the height as 1.
                    return steps;
                }
                
                for (int j = 0; j < 4; ++j) {
                    int r = n.row + dirR[j];
                    int c = n.col + dirC[j];
    
                    if ((r >= 0 && r < forest.size()) &&
                        (c >= 0 && c < forest[0].size()) &&
                        (forest[r][c] > 0) && (visited[r][c] == 0)) {
                        
                        Node neighbor = Node(r, c, forest[r][c]);
                        q.push(neighbor);
                        //should not set the neighbor.height = 1 here as it will be accessed in the following bfs calls
                        visited[r][c] = 1;
                    }
                }
            }
            
            steps++;
        }   
        
        return -1;
    }
};
代码下载链接: https://pan.quark.cn/s/a4b39357ea24 依据所提供的文件资料,可以归纳出以下关于“数字三角形 C++”的相关知识要点: ## 数字三角形问概述 数字三角形问是指在一个由数字构成的三角形中,寻找一条从顶部到底部的路径,使得该路径上数字的总和达到最大值。这个问可以通过动态规划技术进行求解。 ### 问定义 给定一个数字三角形,其结构如下所示: ``` 3 7 4 2 4 6 8 5 9 3 ``` 目标是从顶端出发到达最底端的一行,并找到一条路径,使得该路径上数字的累计值最大。例如,在上述示例中,路径 `3 → 7 → 4 → 9` 的总和为 23,这是所有可能路径中的最大数值。 ### 动态规划算法 #### 解决思路 1. **初始设定**:假定三角形的第0行为1个元素,第1行为2个元素,依此类推。 2. **递推关系式**:对于每一个位置 `(row, col)`,可以选择下一行的两个相邻元素之一进行相加,即 `tridata[row][col] += max(tridata[row+1][col], tridata[row+1][col+1])`。 3. **求解终点**:最终的最大值位于三角形的顶端位置,即 `tridata[0][0]`。 #### 算法步骤 1. **输入阶段**:读取用户输入的三角形高度 `n` 以及各节点的数值。 2. **计算环节**:从倒数第二行开始,逐行逐列更新每个节点的值。 3. **结果输出**:输出计算得出的最大路径和。 ### 示例代码解析 ```cpp int GetMax(int tridata[20][20], int &Num) { // 从倒数第二行开始...
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值