leetcode 1631.最小体力消耗路径

思路:BFS+二分

这道题和洛谷上的那个“汽车拉力赛”那道题很相似,但是这道题相较于洛谷那个来说会简单一些。

这里作者一开始写的时候思路堵在了怎么在BFS中用二分,先入为主的以为需要先写出来搜索函数然后再去处理二分的事,但是这里是先二分找数,然后再搜索才是对的。所以先入为主之后就没有做出来。

注意:需要注意数据范围,另外,每一次更新mid数值的时候,我们上一次已经搜索过的数组,队列等存储单元都需要清空,不然的话会影响后面的输出结果。还有,二分注意用哪一个模板,选择也是很重要的。这里主要是求最小值,所以是(left+right)/2而不是(left+right+1)/2,还有就是while中不要left<=right,你用范围的二分查找会造成死循环,但是用于基本的找数是可以的。

class Solution {
public:
    int minimumEffortPath(vector<vector<int>>& heights) {
        int dx[4]={1,-1,0,0};
        int dy[4]={0,0,1,-1};
        int left=0;
        int right=1000000;
        while(left<right){
            queue<pair<int,int>>q;
            q.push({0,0});
            vector<vector<bool>>st(heights.size(),vector<bool>(heights[0].size(),false));
            st[0][0]=true;
            int mid=(left+right)/2;
        while(!q.empty()){
            auto tmp=q.front();
            q.pop();
            for(int i=0;i<4;i++){
                int a=dx[i]+tmp.first;
                int b=dy[i]+tmp.second;
                if(a>=heights.size()||a<0||b<0||b>=heights[0].size())continue;
                if(st[a][b])continue;
                if(abs(heights[a][b]-heights[tmp.first][tmp.second])>mid)continue;

                q.push({a,b});
                st[a][b]=true;
            }
        }
        if(st[heights.size()-1][heights[0].size()-1])
        {
            right=mid;
        }
        else
        {
            left=mid+1;
        }
        }
        return right;
    }
};

### Dijkstra算法LeetCode中的应用 #### 1631. 最小体力消耗路径 此题要求找到一条从左上角到右下角的路径,使得路径上的最大绝对高度差最小。可以利用Dijkstra算法来解决这个问题,在每次扩展节点时记录当前的最大高度差,并以此作为优先级队列的选择标准[^1]。 ```cpp class Solution { public: int minimumEffortPath(vector<vector<int>>& heights) { using PII = pair<int, int>; priority_queue<PII, vector<PII>, greater<>> pq; const int dirs[] = {-1, 0, 1, 0, -1}; int m = (int)heights.size(); int n = (int)heights[0].size(); vector<vector<bool>> visited(m, vector<bool>(n)); pq.emplace(0, 0); while (!pq.empty()) { auto [effort, code] = pq.top(); pq.pop(); int i = code / n, j = code % n; if (visited[i][j]) continue; if (i == m-1 && j == n-1) return effort; visited[i][j] = true; for (int d = 0; d < 4; ++d) { int r = i + dirs[d], c = j + dirs[d+1]; if (r >= 0 && r < m && c >= 0 && c < n && !visited[r][c]) pq.emplace(max(effort, abs(heights[i][j]-heights[r][c])), r*n+c); } } __builtin_unreachable(); } }; ``` #### 1368. 使网格至少有一个有效路径最小代价 该问题旨在寻找一种方法改变某些边的方向,从而让起点能够到达终点,目标是最小化修改的成本总和。这里同样采用Dijkstra变种的方式处理有向图中最短路的问题[^3]。 ```python import heapq from typing import List def minCost(self, grid: List[List[int]]) -> int: M,N=len(grid),len(grid[0]) dis=[[float('inf')]*N for _ in range(M)] q=[(0,0,0)] #(distance,x,y) while q: cur_dis,i,j=heapq.heappop(q) if not (0<=i<M and 0<=j<N):continue if dis[i][j]<=cur_dis:continue dis[i][j]=cur_dis directions={1:(0,1),2:(0,-1),3:(1,0),4:(-1,0)} next_directions=[directions.get(grid[i][j]),(-grid[i][j]%2*2+1,0),(0,-grid[i][j]%2*2+1)] for di,dj in next_directions+[v for k,v in directions.items()]: ni,nj=i+di,j+dj new_cost=(cur_dis+(ni!=i or nj!=j)) heapq.heappush(q,(new_cost,ni,nj)) return dis[-1][-1] ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值