题目描述

这是 LeetCode 上的 675. 为高尔夫比赛砍树 ,难度为 困难

Tag : 「图论 BFS」、「AStar 算法」、「启发式搜索」、「并查集」

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

  • 表示障碍,无法触碰
  •  表示地面,可以行走
  • 比 大的数 表示有树的单元格,可以行走,数值表示树的高度

每一步,你都可以向上、下、左、右四个方向之一移动一个单位,如果你站的地方有一棵树,那么你可以决定是否要砍倒它。

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

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

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

示例 1:

输入:forest = [[1,2,3],[0,0,4],[7,6,5]]

输出:6

解释:沿着上面的路径,你可以用 6 步,按从最矮到最高的顺序砍掉这些树。

示例 2:

输入: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) 位置的树,可以直接砍去,不用算步数。

提示:

基本分析

基本题意为:给定一个 的矩阵,每次能够在当前位置往「四联通」移动一个单位,其中 的位置代表障碍(无法访问), 的位置代表平地(可直接访问,且无须进行任何决策),其余大于 的位置代表有树,经过该位置的时候可以考虑将树砍掉(相应值变为平地 )。

同时题目限定了我们只能按照「从低到高」的顺序进行砍树,并且图中不存在高度相等的两棵树,这意味着 整个砍树的顺序唯一确定,就是对所有有树的地方进行「高度」排升序,即是完整的砍树路线。

而另外一个更为重要的性质是:点与点之间的最短路径,不会随着砍树过程的进行而发生变化(某个树点被砍掉,只会变为平地,不会变为阻碍点,仍可通过)。

综上,砍树的路线唯一确定,当我们求出每两个相邻的砍树点最短路径,并进行累加即是答案(整条砍树路径的最少步数)

BFS

因此,再结合数据范围只有 ,并且点与点之间边权为 (每次移动算一步),我们可以直接进行 BFS 进行求解。

先对整张图进行一次遍历,预处理出所有的树点(以三元组 的形式进行存储),并对其以 排升序,得到唯一确定的砍树路径。

之后就是计算砍树路径中相邻点的最短距离,运用 BFS 求解任意两点的最短路径复杂度为 ,我们最多有 个树点,因此整体复杂度为 。

求解相邻点的最短距离的部分也是整个算法的复杂度上界,数据范围只有 ,计算量不超过 ,可以过。

代码:

class Solution {    int N = 50;    int[][] g = new int[N][N];    int n, m;    List<int[]> list = new ArrayList<>();    public int cutOffTree(List<List<Integer>> forest) {        n = forest.size(); m = forest.get(0).size();        for (int i = 0; i < n; i++) {            for (int j = 0; j < m; j++) {                g[i][j] = forest.get(i).get(j);                if (g[i][j] > 1) list.add(new int[]{g[i][j], i, j});            }        }        Collections.sort(list, (a,b)->a[0]-b[0]);        if (g[0][0] == 0) return -1;        int x = 0, y = 0, ans = 0;        for (int[] ne : list) {            int nx = ne[1], ny = ne[2];            int d = bfs(x, y, nx, ny);            if (d == -1) return -1;            ans += d;            x = nx; y = ny;        }        return ans;    }    int[][] dirs = new int[][]{{0,1},{0,-1},{1,0},{-1,0}};    int bfs(int X, int Y, int P, int Q) {        if (X == P && Y == Q) return 0;        boolean[][] vis = new boolean[n][m];        Deque<int[]> d = new ArrayDeque<>();        d.addLast(new int[]{X, Y});        vis[X][Y] = true;        int ans = 0;        while (!d.isEmpty()) {            int size = d.size();            while (size-- > 0) {                int[] info = d.pollFirst();                int x = info[0], y = info[1];                for (int[] di : dirs) {                    int nx = x + di[0], ny = y + di[1];                    if (nx < 0 || nx >= n || ny < 0 || ny >= m) continue;                    if (g[nx][ny] == 0 || vis[nx][ny]) continue;                    if (nx == P && ny == Q) return ans + 1;                    d.addLast(new int[]{nx, ny});                    vis[nx][ny] = true;                }            }            ans++;        }        return -1;    }}
  • 时间复杂度:预处理出所有树点的复杂度为 ,对树点进行排序的复杂度为 ,最多有 个树点,对每两个相邻树点运用 BFS 求最短路的复杂度为 ,统计完整路径的复杂度为
  • 空间复杂度:

AStar 算法

由于问题的本质是求最短路,同时原问题的边权为 ,因此套用其他复杂度比 BFS 高的最短路算法,对于本题而言是没有意义,但运用启发式搜索 AStar 算法来优化则是有意义。

因为在 BFS 过程中,我们会无差别往「四联通」方向进行搜索,直到找到「当前树点的下一个目标位置」为止,而实际上,两点之间的最短路径往往与两点之间的相对位置相关。

举个

【宫水三叶的刷题日记】675. 为高尔夫比赛砍树(困难)相关推荐

  1. 【宫水三叶的刷题日记】961. 在长度 2N 的数组中找出重复 N 次的元素

    题目描述 这是 LeetCode 上的 961. 在长度 2N 的数组中找出重复 N 次的元素 ,难度为 简单. Tag : 「模拟」.「计数」.「构造」.「哈希表」 给你一个整数数组 nums ,该 ...

  2. 【宫水三叶的刷题日记】1022. 从根到叶的二进制数之和

    题目描述 这是 LeetCode 上的 1022. 从根到叶的二进制数之和 ,难度为 简单. Tag : 「DFS」.「BFS」.「二叉树」.「树的遍历」 给出一棵二叉树,其上每个结点的值都是   或 ...

  3. 【宫水三叶的刷题日记】1037. 有效的回旋镖(简单)

    题目描述 这是 LeetCode 上的 1037. 有效的回旋镖 ,难度为 简单. Tag : 「计算几何」.「数学」 给定一个数组 points,其中   表示 X-Y 平面上的一个点,如果这些点构 ...

  4. 【宫水三叶的刷题日记】497. 非重叠矩形中的随机点(中等)

    题目描述 这是 LeetCode 上的 497. 非重叠矩形中的随机点 ,难度为 中等. Tag : 「前缀和」.「二分」.「随机化」 给定一个由非重叠的轴对齐矩形的数组 rects,其中 表示 是第 ...

  5. 【宫水三叶的刷题日记】732. 我的日程安排表 III

    题目描述 这是 LeetCode 上的 「732. 我的日程安排表 III」 ,难度为 「困难」. Tag : 「线段树(动态开点)」.「分块」.「线段树」 当 个日程安排有一些时间上的交叉时(例如 ...

  6. 【宫水三叶的刷题日记】209. 长度最小的子数组(中等)

    题目描述 这是 LeetCode 上的 209. 长度最小的子数组 ,难度为 中等. Tag : 「前缀和」.「二分」 给定一个含有 n 个正整数的数组和一个正整数 target. 找出该数组中满足其 ...

  7. 【宫水三叶的刷题日记】715. Range 模块

    题目描述 这是 LeetCode 上的 715. Range 模块 ,难度为 困难. Tag : 「线段树」.「线段树(动态开点)」 Range 模块是跟踪数字范围的模块.设计一个数据结构来跟踪表示为 ...

  8. 【宫水三叶的刷题日记】730. 统计不同回文子序列(困难)

    题目描述 这是 LeetCode 上的 730. 统计不同回文子序列 ,难度为 困难. Tag : 「区间 DP」.「动态规划」 给定一个字符串 s,返回 s 中不同的非空「回文子序列」个数 . 通过 ...

  9. 【宫水三叶的刷题日记】508. 出现次数最多的子树元素和

    题目描述 这是 LeetCode 上的 508. 出现次数最多的子树元素和 ,难度为 中等. Tag : 「树的遍历」.「DFS」.「哈希表」 给你一个二叉树的根结点 root,请返回出现次数最多的子 ...

  10. 【宫水三叶的刷题日记】468. 验证IP地址

    题目描述 这是 LeetCode 上的 468. 验证IP地址 ,难度为 中等. Tag : 「模拟」.「双指针」 给定一个字符串 queryIP.如果是有效的 IPv4 地址,返回 "IP ...

最新文章

  1. java语法结构是什么意思_java - 基础 - 语法结构
  2. 雅客EXCEL(5)-tab键、同组数据录入、提取重复值、提取身份证号码的出生日期
  3. java循环语句三角形_JAVA——程序流程控制——循环语句——for循环(打印三角形)...
  4. ubuntu系统中samba服务器搭建
  5. 和远程ip_【漏洞预警】Windows TCP/IP远程执行代码漏洞(CVE202016898)
  6. 用状态机STATE MACHINE实现有选择的文件转换
  7. [置顶]android ListView包含Checkbox滑动时状态改变
  8. 眼坐标系和世界坐标系的相互转换
  9. 机器学习基础(四十七)—— 统计
  10. iOS开发GCD(3)-数据安全
  11. graphpad饼状图_应用 Graphpad 统计作图,助你写文章事半功倍
  12. android 的User-Agen
  13. 如何查看网站被搜索引擎收录的情况
  14. 记录java使用EasyExcel进行单元格内换行操作
  15. 【转】web.xml不同版本的头
  16. Xiaocao's first blog post
  17. 智能家居系列之智能家居平台设计
  18. Asp.net Ajax框架教程[教程下载]
  19. 亚马逊推出的「距离助手」,好像孙悟空给唐僧画的圈圈啊
  20. css 多文件上传框美化

热门文章

  1. 黑马程序员_输入输出流(I/O)
  2. 【记录】微信网页授权错误码10003:redirect_uri域名与后台配置不一致
  3. 【直播回顾】OpenHarmony知识赋能六期第五课—WiFi子系统
  4. 南大计算机系为啥不升格为学院,浙江科技学院更名失败了吗?升格成大学没有...
  5. 智能视频已上线,提供50+AI算法
  6. html input提交按钮标签样式,html - 输入类型=“提交”Vs按钮标签是否可以互换?...
  7. 4.3计算机动画制作 教案,高中信息技术选修2教案-4.3.1 选择计算机动画制作工具1-教科版.docx...
  8. 堕落都是从疏远了运动开始的
  9. MySQL主从复制中,从数据库复制指定的数据表(数据库表级复制)
  10. java公钥加密私钥解密_公钥加密,私钥解密示例程序(JAVA)详解