题目

https://leetcode.com/problems/path-with-minimum-effort/

每个节点的height不同,矩阵从左上走到右下,求最小体力消耗

当前点体力消耗:max(来的那个节点的effort,|来的那个节点height-当前节点height|)

总最小体力消耗:所选路径加起来

You are a hiker preparing for an upcoming hike. You are given heights, a 2D array of size rows x columns, where heights[row][col] represents the height of cell (row, col). You are situated in the top-left cell, (0, 0), and you hope to travel to the bottom-right cell, (rows-1, columns-1) (i.e., 0-indexed). You can move up, down, left, or right, and you wish to find a route that requires the minimum effort.

A route's effort is the maximum absolute difference in heights between two consecutive cells of the route.

Return the minimum effort required to travel from the top-left cell to the bottom-right cell.

 

Example 1:

Input: heights = [[1,2,2],[3,8,2],[5,3,5]]
Output: 2
Explanation: The route of [1,3,5,3,5] has a maximum absolute difference of 2 in consecutive cells.
This is better than the route of [1,2,2,2,5], where the maximum absolute difference is 3.

Example 2:

Input: heights = [[1,2,3],[3,8,4],[5,3,5]]
Output: 1
Explanation: The route of [1,2,3,4,5] has a maximum absolute difference of 1 in consecutive cells, which is better than route [1,3,5,3,5].

Example 3:

Input: heights = [[1,2,1,1,1],[1,2,1,2,1],[1,2,1,2,1],[1,2,1,2,1],[1,1,1,2,1]]
Output: 0
Explanation: This route does not require any effort.

 

 

思路

dijktra+优先队列

迪杰斯特拉算法:https://www.bilibili.com/video/BV1zz4y1m7Nq

dijktra可以理解成一种BFS,即向相邻节点搜索,

eg 到第i个节点,比较(到第i-1个节点的长+去第i个节点的长)和(第0个节点直接到第i个节点的长)

如果更小,就更新路径,并记录在是从i-1节点过来的

 

优先队列主要是理解comparator比较器的设置,参考相关priorityqueue的题

代码

 

class Solution {
    final int[][] direction={{-1,0},{1,0},{0,-1},{0,1}};
    public int minimumEffortPath(int[][] heights) {
        int m=heights.length;
        int n=heights[0].length;
        int[][] cost=new int[m][n];//动态的存储到每个点的最小effort
        for(int i=0;i<m;i++){
            for(int j=0;j<n;j++){
                cost[i][j]=Integer.MAX_VALUE;//先全部设为极大值,后面更新
            }
        }
        cost[0][0]=0;//起始点

        //pq设置根据【位置2】(cost)升序排列,即小的在前
        PriorityQueue<int[]> pq = new PriorityQueue<>((a, b) -> Integer.compare(a[2], b[2]));
        pq.offer(new int[]{0,0,0});//{点n的x位置,点n的y位置,cost},即到这个点的最小effort

        while(!pq.isEmpty()){
            //取出目前走到的矩阵位置
            int[] cur=pq.poll();
            int i=cur[0];
            int j=cur[1];
            
            //如果已经走到右下角,返回结果
            if(i==m-1&&j==n-1)
                break;
            
            //反之,朝上下左右4个direction试探
            for(int[] dir:direction){
                //下一步,试探的位置
                int x=i+dir[0];
                int y=j+dir[1];
                //如果越界
                if(x<0||y<0||x>=m||y>=n){
                    continue;
                }
                //试探位置的cost计算,最大effort
                //取俩者大的 上一步cost即cur[2],试探位置与试探位置的绝对值
                int curCost=Math.max(cur[2],Math.abs(heights[x][y]-heights[i][j]));
                if(curCost<cost[x][y]){
                    //pq.offer(new int[]{x,y,curCost});//这里有问题
                    cost[x][y]=curCost;//要记得更新cost!!不然一直是MAX_VALUE
                    
                    //更新pq
                    pq.offer(new int[]{x,y,curCost});
                }
            }
        }
        
        //返回到右下角这个点的min effort
        return cost[m-1][n-1];
    }
}

 

 posted on 2021-11-30 06:12  alau  阅读(38)  评论(0编辑  收藏  举报