文章目录
- 题目链接:
- 题目描述:
- 解法
- C++ 算法代码:
题目链接:
675. 为高尔夫比赛砍树
题目描述:
解法
注意:砍树要从低到高砍。
砍掉1,从1到5到2
砍掉2,从2到5到3
砍掉3,从3到5到2到6到4
砍掉4,从4到6到5
砍掉5,从5到6
砍掉6
变成若干个迷宫问题了。
把所有的最小值求出来然后加起来。
但是有个问题,你怎么知道砍树的顺序呢?
所以我们要先找到砍树的顺序,弄个二维数组先存一下下标和内容,然后按照内容由小到大排序。
C++ 算法代码:
class Solution {int m, n; // 森林的行数和列数public:int cutOffTree(vector<vector<int>>& f) {m = f.size(), n = f[0].size();// 1. 准备工作:找出所有需要砍的树,并按树的高度排序vector<pair<int, int>> trees;for (int i = 0; i < m; i++)for (int j = 0; j < n; j++)if (f[i][j] > 1) // 树的高度大于1才需要砍trees.push_back({i, j});// 按照树的高度从小到大排序sort(trees.begin(), trees.end(),[&](const pair<int, int>& p1, const pair<int, int>& p2) {return f[p1.first][p1.second] < f[p2.first][p2.second];});// 2. 按照顺序砍树int bx = 0, by = 0; // 起始位置(0,0)int ret = 0; // 总步数for (auto& [a, b] : trees) {// 计算从当前位置到下一棵树的最短步数int step = bfs(f, bx, by, a, b);if (step == -1) // 如果无法到达,返回-1return -1;ret += step; // 累加步数bx = a, by = b; // 更新当前位置}return ret;}bool vis[51][51]; // 访问标记数组int dx[4] = {0, 0, 1, -1}; // 四个方向的x偏移量int dy[4] = {1, -1, 0, 0}; // 四个方向的y偏移量// BFS计算从起点(bx,by)到终点(ex,ey)的最短步数int bfs(vector<vector<int>>& f, int bx, int by, int ex, int ey) {if (bx == ex && by == ey) // 如果起点就是终点,返回0步return 0;queue<pair<int, int>> q;memset(vis, 0, sizeof vis); // 清空访问标记q.push({bx, by});vis[bx][by] = true;int step = 0;while (q.size()) {step++;int sz = q.size();// 处理当前层的所有节点while (sz--) {auto [a, b] = q.front();q.pop();// 尝试四个方向for (int i = 0; i < 4; i++) {int x = a + dx[i], y = b + dy[i];// 检查新位置是否合法if (x >= 0 && x < m && y >= 0 && y < n && f[x][y] != 0 && !vis[x][y]) { // 0表示不能走的障碍物// 找到终点,返回当前步数if (x == ex && y == ey)return step;q.push({x, y});vis[x][y] = true;}}}}return -1; // 无法到达终点}
};