[Leetcode] 675. Cut Off Trees for Golf Event 解题报告

本文介绍了一道经典的算法题目,任务是在一个二维地图中按树木的高度顺序砍伐所有树木,并计算行走的最短路径。文章详细解释了解题思路及采用BFS算法求解两点间最短距离的方法。

题目

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:

  1. 0 represents the obstacle can't be reached.
  2. 1 represents the ground can be walked through.
  3. 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 1:

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

Example 2:

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

Example 3:

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.

Hint: size of the given matrix will not exceed 50x50.

思路

这道题目本质上是求平面上两点的最短距离。我们首先将需要砍的树按照高度从低到高排列起来,然后依次计算相邻两棵树之间的距离,最后返回距离之和即可。如果有任何两棵相邻的树之间无法到达,则我们返回-1。所以关键是求两点之间的距离:采用BFS就是标配的解法了。

代码

class Solution {
public:
    int cutOffTree(vector<vector<int>>& forest) {
        vector<vector<int>> trees;
        for (int r = 0; r < forest.size(); ++r) {
            for (int c = 0; c < forest[r].size(); ++c) {
                if (forest[r][c] > 1) {
                    trees.push_back({forest[r][c], r, c});
                }
            }
        }
        trees.push_back({1, 0, 0});     // add the start position
        sort(trees.begin(), trees.end());
        int ans = 0, dist = 0;
        for (int i = 0; i + 1 < trees.size(); ++i) {
            int r1 = trees[i][1], c1 = trees[i][2];
            int r2 = trees[i + 1][1], c2 = trees[i + 1][2];
            dist = getDistance(forest, r1, c1, r2, c2);
            if (dist == -1) {
                return -1;
            }
            ans += dist;
        }
        return ans;
    }
private:
    int getDistance(vector<vector<int>> &forest, int r1, int c1, int r2, int c2) {
        int row_num = forest.size(), col_num = forest[0].size();
        vector<vector<bool>> visited(row_num, vector<bool>(col_num, false));
        queue<vector<int>> q;   // 0: x, 1: y, 2: dist
        q.push({r1, c1, 0});
        visited[r1][c1] = true;
        while (!q.empty()) {
            vector<int> vec = q.front();
            int r = vec[0], c = vec[1], dist = vec[2];
            q.pop();
            if (r == r2 && c == c2) {
                return dist;
            }
            if (r > 0 && !visited[r - 1][c] && forest[r - 1][c]) {
                q.push({r - 1, c, dist + 1});
                visited[r - 1][c] = true;
            }
            if (r + 1 < row_num && !visited[r + 1][c] && forest[r + 1][c]) {
                q.push({r + 1, c, dist + 1});
                visited[r + 1][c] = true;
            }
            if (c > 0 && !visited[r][c - 1] && forest[r][c - 1]) {
                q.push({r, c - 1, dist + 1});
                visited[r][c - 1] = true;
            }
            if (c + 1 < col_num && !visited[r][c + 1] && forest[r][c + 1]) {
                q.push({r, c + 1, dist + 1});
                visited[r][c + 1] = true;
            }
        }
        return -1;
    }
};
<think>好的,我现在需要解决用户的问题:如何调整CUT参数中的阈值百分比以满足最小指定百分比要求。首先,我需要理解用户提到的CUT参数具体是什么。根据用户提供的引用内容,尤其是引用[3],他们可能在处理类似iris数据集的情况,其中涉及到设定一个阈值(比如occ_cutoff =5.2)来计算某个指标在各组的出现率。用户希望调整这个阈值,使得覆盖的区域满足最小百分比要求。 首先,我需要确定CUT参数的作用。在引用[3]的代码中,阈值occ_cutoff被用来计算每组中Sepal.Length超过该值的比例。例如,当阈值为5.2时,计算每个Species组中Sepal.Length大于5.2的比例。用户的问题可能是希望调整这个阈值,使得至少达到某个最小覆盖率(比如覆盖至少X%的数据点)。 接下来,我需要思考如何动态调整阈值以满足最小百分比。通常,这可以通过反向查找来实现:即找到最大的阈值,使得在该阈值下,覆盖率(即超过该阈值的数据比例)不低于用户指定的最小百分比。例如,如果用户希望至少覆盖30%的数据,那么需要找到最大的阈值,使得超过该值的数据点至少占30%。 在引用[3]中,阈值是固定的(5.2),但用户可能需要一个动态的方法。可能需要使用分位数函数来确定阈值。例如,若想覆盖至少p%的数据,可以将阈值设为该变量的(1-p)分位数。例如,若p=30%,则阈值应设为数据中70%分位数,这样有30%的数据点超过该阈值。 在R语言中,可以使用quantile函数来实现这一点。例如,对于iris数据集中的Sepal.Length变量,若要确保至少30%的数据超过阈值,可以计算该变量的70%分位数: threshold <- quantile(iris$Sepal.Length, probs = 0.7) 然后,将这个threshold代入到occ_cutoff的位置,重新计算各组的出现率。这样就能保证整体数据中有30%超过该阈值,但需要检查每个组的覆盖率是否满足要求,或者是否整体满足。 不过,用户的问题中提到“覆盖足够的区域”,可能需要的是每个组的覆盖率都满足最小百分比,或者整体的覆盖率。如果是每个组都需要满足,可能需要分别对每个组计算分位数,但这样会导致不同的阈值,这可能不符合用户的需求。因此,更可能的情况是用户希望整体或特定组的覆盖率满足要求,因此需要统一调整阈值。 此外,引用[1]中提到了调整分类阈值的方法,通过改变概率阈值来影响分类结果,这可能与调整CUT参数类似。例如,在逻辑回归中,降低阈值会增加正类的比例,从而提高覆盖率。类似地,在当前的上下文中,降低阈值(比如从5.2降到更低的值)会增加超过阈值的数据点数量,从而提高覆盖率,反之提高阈值会减少覆盖率。因此,调整阈值的方向取决于用户的需求是提高还是降低覆盖率。 总结步骤: 1. 确定用户的最小指定百分比是整体还是各组的覆盖率。 2. 计算当前阈值下的覆盖率,查看是否满足要求。 3. 若不满足,调整阈值:降低阈值以提高覆盖率,提高阈值以降低覆盖率。 4. 使用分位数方法动态计算阈值,使得恰好满足最小百分比要求。 5. 在代码中替换原有的固定阈值,使用动态计算的阈值。 例如,在R中,若用户希望确保整体至少有p%的数据超过阈值,可以使用quantile函数计算对应的阈值: occ_cutoff <- quantile(plotdata$Index, probs = 1 - p) 然后,使用这个occ_cutoff代替原来的固定值。如果用户希望每个组都满足,可能需要分别对每个组计算分位数,但这可能导致不同的阈值,需要进一步处理。 另外,用户可能需要一个函数来自动调整阈值,直到满足最小覆盖率。这可以通过迭代方法或直接分位数计算来实现。分位数方法更高效,因为它直接找到对应的阈值。 最后,验证调整后的阈值是否满足要求,并确保代码中的相关部分(如计算出现率的函数)使用新的阈值。</think>要调整CUT参数的阈值百分比以满足最小覆盖率要求,可以通过以下步骤实现: ### 1. 理解阈值与覆盖率的关系 阈值百分比$T$与覆盖率成反比:**降低阈值会增加覆盖区域的比例**,反之则减少。例如,在iris数据集中,若将`Sepal.Length`的阈值从5.2降低到4.8,满足条件的数据点比例会显著增加[^3]。 ### 2. 动态计算阈值 使用**分位数函数**直接计算满足最小覆盖率要求的阈值。例如,若要求覆盖至少$p\%$的数据,则阈值$T$应为数据列的$(1-p)\%$分位数: $$T = \text{quantile}(X, 1-p)$$ 其中$X$为目标指标列,$p$为最小覆盖率要求(如0.3表示30%)。 #### 修改后的R代码示例: ```r # 设定最小覆盖率为30% min_coverage <- 0.3 # 动态计算阈值(使用Sepal.Length列) occ_cutoff <- quantile(iris$Sepal.Length, probs = 1 - min_coverage) # 更新计算出现率的函数 occ_fun <- function(x) { return(round(length(x[x > occ_cutoff])/length(x), 4)) } ``` ### 3. 验证覆盖率 通过分组统计确认调整后的阈值是否满足要求: ```r plotOcc <- plotdata |> dplyr::group_by(Group) |> dplyr::summarise(occ = occ_fun(Index)) ``` ### 4. 阈值调整策略对比 | 方法 | 实现复杂度 | 适用场景 | 示例场景 | |------------|------------|-----------------------|-----------------------| | 分位数法 | 低 | 全局覆盖率要求 | 确保整体数据覆盖30% | | 迭代调整 | 高 | 分组覆盖率要求 | 每个物种组均覆盖20% | | 手动试探 | 中 | 小数据集/临时调试 | 交互式分析时快速验证 | ### 5. 进阶优化(分组覆盖率) 若需**每个分组均满足最小覆盖率**,需对每个组单独计算分位数: ```r grouped_thresholds <- plotdata |> dplyr::group_by(Group) |> dplyr::summarise(cutoff = quantile(Index, 1 - min_coverage)) # 合并阈值回原数据 plotdata <- plotdata |> dplyr::left_join(grouped_thresholds, by = "Group") |> dplyr::mutate(IsCovered = Index > cutoff) ```
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值