from collections import deque
class Solution:
def cutOffTree(self, forest):
if not forest or not forest[0]:
return -1
rows, cols = len(forest), len(forest[0])
# Collect all trees in sorted order of height
trees = sorted((h, r, c)
for r, row in enumerate(forest)
for c, h in enumerate(row) if h > 1)
def bfs(sr, sc, tr, tc):
if sr == tr and sc == tc:
return 0
visited = [[False] * cols for _ in range(rows)]
queue = deque([(sr, sc, 0)])
visited[sr][sc] = True
while queue:
r, c, d = queue.popleft()
for dr, dc in [(-1,0),(1,0),(0,-1),(0,1)]:
nr, nc = r + dr, c + dc
if 0 <= nr < rows and 0 <= nc < cols and not visited[nr][nc] and forest[nr][nc] != 0:
if nr == tr and nc == tc:
return d + 1
visited[nr][nc] = True
queue.append((nr, nc, d + 1))
return -1
total_steps = 0
sr = sc = 0
for _, tr, tc in trees:
steps = bfs(sr, sc, tr, tc)
if steps == -1:
return -1
total_steps += steps
sr, sc = tr, tc
return total_steps
#include <vector>
#include <queue>
#include <algorithm>
using namespace std;
class Solution {
public:
int cutOffTree(vector<vector<int>>& forest) {
int rows = forest.size(), cols = forest[0].size();
vector<tuple<int,int,int>> trees;
for (int r = 0; r < rows; ++r)
for (int c = 0; c < cols; ++c)
if (forest[r][c] > 1)
trees.push_back({forest[r][c], r, c});
sort(trees.begin(), trees.end());
auto bfs = [&](int sr, int sc, int tr, int tc) {
if (sr == tr && sc == tc) return 0;
vector<vector<bool>> visited(rows, vector<bool>(cols, false));
queue<tuple<int,int,int>> q;
q.push({sr, sc, 0});
visited[sr][sc] = true;
int dirs[4][2] = {{-1,0},{1,0},{0,-1},{0,1}};
while (!q.empty()) {
auto [r, c, d] = q.front(); q.pop();
for (auto& dir : dirs) {
int nr = r + dir[0], nc = c + dir[1];
if (nr >= 0 && nr < rows && nc >= 0 && nc < cols && !visited[nr][nc] && forest[nr][nc] != 0) {
if (nr == tr && nc == tc) return d + 1;
visited[nr][nc] = true;
q.push({nr, nc, d + 1});
}
}
}
return -1;
};
int sr = 0, sc = 0, total_steps = 0;
for (auto& [_, tr, tc] : trees) {
int steps = bfs(sr, sc, tr, tc);
if (steps == -1) return -1;
total_steps += steps;
sr = tr; sc = tc;
}
return total_steps;
}
};
import java.util.*;
class Solution {
public int cutOffTree(List<List<Integer>> forest) {
int rows = forest.size(), cols = forest.get(0).size();
List<int[]> trees = new ArrayList<>();
for (int r = 0; r < rows; ++r)
for (int c = 0; c < cols; ++c)
if (forest.get(r).get(c) > 1)
trees.add(new int[]{forest.get(r).get(c), r, c});
trees.sort(Comparator.comparingInt(a -> a[0]));
int sr = 0, sc = 0, total_steps = 0;
for (int[] tree : trees) {
int steps = bfs(forest, sr, sc, tree[1], tree[2]);
if (steps == -1) return -1;
total_steps += steps;
sr = tree[1]; sc = tree[2];
}
return total_steps;
}
private int bfs(List<List<Integer>> forest, int sr, int sc, int tr, int tc) {
if (sr == tr && sc == tc) return 0;
int rows = forest.size(), cols = forest.get(0).size();
boolean[][] visited = new boolean[rows][cols];
Queue<int[]> queue = new LinkedList<>();
queue.offer(new int[]{sr, sc, 0});
visited[sr][sc] = true;
int[][] dirs = {{-1,0},{1,0},{0,-1},{0,1}};
while (!queue.isEmpty()) {
int[] curr = queue.poll();
for (int[] dir : dirs) {
int nr = curr[0] + dir[0], nc = curr[1] + dir[1];
if (nr >= 0 && nr < rows && nc >= 0 && nc < cols &&
!visited[nr][nc] && forest.get(nr).get(nc) != 0) {
if (nr == tr && nc == tc) return curr[2] + 1;
visited[nr][nc] = true;
queue.offer(new int[]{nr, nc, curr[2] + 1});
}
}
}
return -1;
}
}
var cutOffTree = function(forest) {
const rows = forest.length, cols = forest[0].length;
let trees = [];
for (let r = 0; r < rows; ++r)
for (let c = 0; c < cols; ++c)
if (forest[r][c] > 1)
trees.push([forest[r][c], r, c]);
trees.sort((a, b) => a[0] - b[0]);
function bfs(sr, sc, tr, tc) {
if (sr === tr && sc === tc) return 0;
let visited = Array.from({length: rows}, () => Array(cols).fill(false));
let queue = [[sr, sc, 0]];
visited[sr][sc] = true;
let dirs = [[-1,0],[1,0],[0,-1],[0,1]];
while (queue.length) {
let [r, c, d] = queue.shift();
for (let [dr, dc] of dirs) {
let nr = r + dr, nc = c + dc;
if (nr >= 0 && nr < rows && nc >= 0 && nc < cols && !visited[nr][nc] && forest[nr][nc] !== 0) {
if (nr === tr && nc === tc) return d + 1;
visited[nr][nc] = true;
queue.push([nr, nc, d + 1]);
}
}
}
return -1;
}
let sr = 0, sc = 0, total_steps = 0;
for (let [_, tr, tc] of trees) {
let steps = bfs(sr, sc, tr, tc);
if (steps === -1) return -1;
total_steps += steps;
sr = tr; sc = tc;
}
return total_steps;
};
The "Cut Off Trees for Golf Event" problem presents you with a 2D grid forest
where each cell contains:
(0, 0)
. The goal is to cut all trees in order of increasing height (from the shortest to the tallest). You can only move up, down, left, or right to adjacent cells that are not obstacles. After cutting a tree, the cell becomes ground (1
).
-1
.
At first glance, the problem seems to require finding a path through a grid, cutting trees as you go. The naive approach might be to try all possible orders or paths, but the problem states we must cut trees in order of increasing height. This constraint greatly simplifies the problem and allows us to plan our approach.
The main challenge becomes: for each tree (in order), what is the shortest path from our current position to the tree's position? Since obstacles may block access to some trees, we must check reachability for each tree before attempting to cut it.
The brute-force approach would be to use depth-first search (DFS) for each tree, but this would be inefficient for large grids. Instead, we can use breadth-first search (BFS) to find the shortest path between two points in a grid, which is optimal for unweighted graphs.
The key realization is that we can process each tree one by one, always moving from our current position to the next tree in sorted order, using BFS for each movement.
We can break down the solution into several clear steps:
Sample Input:
forest = [
[1,2,3],
[0,0,4],
[7,6,5]
]
Step 1: Collect and sort trees
Brute-Force Approach:
If we tried all possible orders, complexity would be factorial in the number of trees, which is infeasible.
Optimized BFS Approach:
T
be the number of trees, R
and C
the grid dimensions.R*C
cells in the worst case.O(T * R * C)
O(R * C)
for the BFS queue and visited array.The "Cut Off Trees for Golf Event" problem is elegantly solved by:
-1
if any tree is unreachable