LeetCode 675. 为高尔夫比赛砍树 广搜 每日一题

问题描述

你被请来给一个要举办高尔夫比赛的树林砍树。树林由一个 m x n 的矩阵表示, 在这个矩阵中:

0 表示障碍,无法触碰
1 表示地面,可以行走
比 1 大的数 表示有树的单元格,可以行走,数值表示树的高度
每一步,你都可以向上、下、左、右四个方向之一移动一个单位,如果你站的地方有一棵树,那么你可以决定是否要砍倒它。

你需要按照树的高度从低向高砍掉所有的树,每砍过一颗树,该单元格的值变为 1(即变为地面)。

你将从 (0, 0) 点开始工作,返回你砍完所有树需要走的最小步数。 如果你无法砍完所有的树,返回 -1 。

可以保证的是,没有两棵树的高度是相同的,并且你至少需要砍倒一棵树。

输入:forest = [[1,2,3],[0,0,4],[7,6,5]]
输出:6
解释:沿着上面的路径,你可以用 6 步,按从最矮到最高的顺序砍掉这些树。

 

输入:forest = [[1,2,3],[0,0,0],[7,6,5]]
输出:-1
解释:由于中间一行被障碍阻塞,无法访问最下面一行中的树。
示例 3:

输入:forest = [[2,3,4],[0,0,5],[8,7,6]]
输出:6
解释:可以按与示例 1 相同的路径来砍掉所有的树。
(0,0) 位置的树,可以直接砍去,不用算步数。

来源:力扣(LeetCode)
链接:https://leetcode.cn/problems/cut-off-trees-for-golf-event
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

Java  广搜

class Solution {
    int[] xs = {0,0,1,-1};
    int[] ys = {1,-1,0,0};
    public int cutOffTree(List<List<Integer>> forest) {
        int row = forest.size();
        int col = forest.get(0).size();
        //存储每棵树的位置
        List<int[]> trees = new ArrayList<>();
        for(int i = 0;i < row;i++){
            for(int j = 0;j < col;j++){
                if(forest.get(i).get(j) > 1){
                    trees.add(new int[]{i,j});
                }
            }
        }
        //按照树的高度排序
        Collections.sort(trees,(a,b) -> forest.get(a[0]).get(a[1]) - forest.get(b[0]).get(b[1]));

        int size = trees.size();
        int ans = 0;
        int curX = 0;
        int curY = 0;
        //遍历第一棵树到第二棵树,第二棵树到第三棵树的步数,全部相加就是结果
        for(int i = 0;i < size;i++){
            int step = bfs(forest,curX,curY,trees.get(i)[0],trees.get(i)[1]);
            if(step == -1) return -1;

            ans += step;
            curX = trees.get(i)[0];
            curY = trees.get(i)[1];
        }
        return ans;
    }
    public int bfs(List<List<Integer>> forest,int curX,int curY,int nextX,int nextY){
        if(curX == nextX && curY == nextY) return 0;
        int row = forest.size();
        int col = forest.get(0).size();

        int step = 0;
        Queue<int[]> queue = new LinkedList<>();
        boolean[][] visible = new boolean[row][col];
        queue.offer(new int[]{curX,curY});
        visible[curX][curY] = true;

        while(!queue.isEmpty()){
            step++;

            int size = queue.size();
            for(int i = 0;i < size;i++){
                int[] temp = queue.poll();
                
                for(int k = 0;k < 4;k++){
                    int x = temp[0] + xs[k];
                    int y = temp[1] + ys[k];

                    if(x >= 0 && y >= 0 && x < row && y < col){
                        if(!visible[x][y] && forest.get(x).get(y) > 0){
                            if(x == nextX && y == nextY) return step;
                            queue.offer(new int[]{x,y});
                            visible[x][y] = true;
                        }
                    }
                }
            }
        }
        return -1;
    }
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

@小红花

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值