【宫水三叶的刷题日记】675. 为高尔夫比赛砍树(困难)
题目描述
这是 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. 为高尔夫比赛砍树(困难)相关推荐
- 【宫水三叶的刷题日记】961. 在长度 2N 的数组中找出重复 N 次的元素
题目描述 这是 LeetCode 上的 961. 在长度 2N 的数组中找出重复 N 次的元素 ,难度为 简单. Tag : 「模拟」.「计数」.「构造」.「哈希表」 给你一个整数数组 nums ,该 ...
- 【宫水三叶的刷题日记】1022. 从根到叶的二进制数之和
题目描述 这是 LeetCode 上的 1022. 从根到叶的二进制数之和 ,难度为 简单. Tag : 「DFS」.「BFS」.「二叉树」.「树的遍历」 给出一棵二叉树,其上每个结点的值都是 或 ...
- 【宫水三叶的刷题日记】1037. 有效的回旋镖(简单)
题目描述 这是 LeetCode 上的 1037. 有效的回旋镖 ,难度为 简单. Tag : 「计算几何」.「数学」 给定一个数组 points,其中 表示 X-Y 平面上的一个点,如果这些点构 ...
- 【宫水三叶的刷题日记】497. 非重叠矩形中的随机点(中等)
题目描述 这是 LeetCode 上的 497. 非重叠矩形中的随机点 ,难度为 中等. Tag : 「前缀和」.「二分」.「随机化」 给定一个由非重叠的轴对齐矩形的数组 rects,其中 表示 是第 ...
- 【宫水三叶的刷题日记】732. 我的日程安排表 III
题目描述 这是 LeetCode 上的 「732. 我的日程安排表 III」 ,难度为 「困难」. Tag : 「线段树(动态开点)」.「分块」.「线段树」 当 个日程安排有一些时间上的交叉时(例如 ...
- 【宫水三叶的刷题日记】209. 长度最小的子数组(中等)
题目描述 这是 LeetCode 上的 209. 长度最小的子数组 ,难度为 中等. Tag : 「前缀和」.「二分」 给定一个含有 n 个正整数的数组和一个正整数 target. 找出该数组中满足其 ...
- 【宫水三叶的刷题日记】715. Range 模块
题目描述 这是 LeetCode 上的 715. Range 模块 ,难度为 困难. Tag : 「线段树」.「线段树(动态开点)」 Range 模块是跟踪数字范围的模块.设计一个数据结构来跟踪表示为 ...
- 【宫水三叶的刷题日记】730. 统计不同回文子序列(困难)
题目描述 这是 LeetCode 上的 730. 统计不同回文子序列 ,难度为 困难. Tag : 「区间 DP」.「动态规划」 给定一个字符串 s,返回 s 中不同的非空「回文子序列」个数 . 通过 ...
- 【宫水三叶的刷题日记】508. 出现次数最多的子树元素和
题目描述 这是 LeetCode 上的 508. 出现次数最多的子树元素和 ,难度为 中等. Tag : 「树的遍历」.「DFS」.「哈希表」 给你一个二叉树的根结点 root,请返回出现次数最多的子 ...
- 【宫水三叶的刷题日记】468. 验证IP地址
题目描述 这是 LeetCode 上的 468. 验证IP地址 ,难度为 中等. Tag : 「模拟」.「双指针」 给定一个字符串 queryIP.如果是有效的 IPv4 地址,返回 "IP ...
最新文章
- java语法结构是什么意思_java - 基础 - 语法结构
- 雅客EXCEL(5)-tab键、同组数据录入、提取重复值、提取身份证号码的出生日期
- java循环语句三角形_JAVA——程序流程控制——循环语句——for循环(打印三角形)...
- ubuntu系统中samba服务器搭建
- 和远程ip_【漏洞预警】Windows TCP/IP远程执行代码漏洞(CVE202016898)
- 用状态机STATE MACHINE实现有选择的文件转换
- [置顶]android ListView包含Checkbox滑动时状态改变
- 眼坐标系和世界坐标系的相互转换
- 机器学习基础(四十七)—— 统计
- iOS开发GCD(3)-数据安全
- graphpad饼状图_应用 Graphpad 统计作图,助你写文章事半功倍
- android 的User-Agen
- 如何查看网站被搜索引擎收录的情况
- 记录java使用EasyExcel进行单元格内换行操作
- 【转】web.xml不同版本的头
- Xiaocao's first blog post
- 智能家居系列之智能家居平台设计
- Asp.net Ajax框架教程[教程下载]
- 亚马逊推出的「距离助手」,好像孙悟空给唐僧画的圈圈啊
- css 多文件上传框美化
热门文章
- 黑马程序员_输入输出流(I/O)
- 【记录】微信网页授权错误码10003:redirect_uri域名与后台配置不一致
- 【直播回顾】OpenHarmony知识赋能六期第五课—WiFi子系统
- 南大计算机系为啥不升格为学院,浙江科技学院更名失败了吗?升格成大学没有...
- 智能视频已上线,提供50+AI算法
- html input提交按钮标签样式,html - 输入类型=“提交”Vs按钮标签是否可以互换?...
- 4.3计算机动画制作 教案,高中信息技术选修2教案-4.3.1 选择计算机动画制作工具1-教科版.docx...
- 堕落都是从疏远了运动开始的
- MySQL主从复制中,从数据库复制指定的数据表(数据库表级复制)
- java公钥加密私钥解密_公钥加密,私钥解密示例程序(JAVA)详解