代码随想录1631最小体力值消耗

题目
你准备参加一场远足活动。给你一个二维 rows x columns 的地图 heights ,其中 heights[row][col] 表示格子 (row, col) 的高度。一开始你在最左上角的格子 (0, 0) ,且你希望去最右下角的格子 (rows-1, columns-1) (注意下标从 0 开始编号)。你每次可以往 上,下,左,右 四个方向之一移动,你想要找到耗费 体力 最小的一条路径。
一条路径耗费的 体力值 是路径上相邻格子之间 高度差绝对值 的 最大值 决定的。请你返回从左上角走到右下角的最小 体力消耗值 。

解题思路
二分查找来确定最小的体力消耗值。首先初始化一个左边界left为0,一个右边界right为1e6(题目中给出的最大高度差)。然后在每次查找过程中,计算出中间值mid,并使用深度优先搜索来判断是否存在一条路径,其中相邻格子之间的高度差绝对值不超过mid。如果存在一条路径,则将right更新为mid,否则将left更新为mid + 1。最终返回left作为最小的体力消耗值。
在深度优先搜索的过程中,我们使用一个visited数组来记录已经访问过的格子,避免重复访问。通过递归的方式,我们可以依次尝试上下左右四个方向的移动,并判断是否满足条件。如果能够到达右下角的格子,则返回true,否则返回false。

代码实现

class Solution {
public:
    int minimumEffortPath(vector<vector<int>>& heights) {
        int rows = heights.size();
        int cols = heights[0].size();
        vector<vector<bool>> visited(rows, vector<bool>(cols, false));
        int left = 0;
        int right = 1e6; // 最大高度差为1e6

        while (left < right) {
            int mid = left + (right - left) / 2;
            if (dfs(heights, visited, 0, 0, mid)) {
                right = mid;
            } else {
                left = mid + 1;
            }
            // 重置visited数组
            visited = vector<vector<bool>>(rows, vector<bool>(cols, false));
        }

        return left;
    }

private:
    bool dfs(vector<vector<int>>& heights, vector<vector<bool>>& visited, int row, int col, int maxDiff) {
        int rows = heights.size();
        int cols = heights[0].size();

        if (row == rows - 1 && col == cols - 1) {
            return true;
        }

        visited[row][col] = true;

        // 上下左右四个方向
        vector<pair<int, int>> directions = {{-1, 0}, {1, 0}, {0, -1}, {0, 1}};

        for (const auto& dir : directions) {
            int newRow = row + dir.first;
            int newCol = col + dir.second;

            if (newRow >= 0 && newRow < rows && newCol >= 0 && newCol < cols
                && !visited[newRow][newCol]
                && abs(heights[row][col] - heights[newRow][newCol]) <= maxDiff) {
                if (dfs(heights, visited, newRow, newCol, maxDiff)) {
                    return true;
                }
            }
        }

        return false;
    }
};
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值