Leecode 1631. 最小体力消耗路径 BFS/并查集/二分/DP

原题链接:Leecode 1631. 最小体力消耗路径

这题还得好好看
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述参考题解:【多解法】DP + 二分+ BFS + 并查集
并查集

class Djset {
public:
    vector<int> parent;
    vector<int> rank;
    Djset(int n): parent(n),rank(n)
    {
        for(int i=0;i<n;i++)
        {
            parent[i]=i;
        }
    }
    int findfather(int x)
    {
        if(x!=parent[x]) 
            parent[x]=findfather(parent[x]);
        return parent[x];
    }
    void merge(int x,int y)
    {
        int fx=findfather(x);
        int fy=findfather(y);
        if(fx!=fy) 
        {
            if(rank[fx]<rank[fy]) swap(fx,fy);
            parent[fy]=fx;
            if(rank[fx]==rank[fy]) rank[fx]+=1;
        }
    }
    bool issame(int x,int y)
    {
        return findfather(x)==findfather(y);
    }
};
struct Edge
{
    int u,v,dis;
    Edge(int _u,int _v,int _dis)
    {
        u=_u; v=_v; dis=_dis;
    }
};
bool cmp(Edge a,Edge b)
{
    return a.dis<b.dis;
};

class Solution {
public:
    
    int minimumEffortPath(vector<vector<int>>& heights) {
        int m=heights.size(),n=heights[0].size();
        vector<Edge> edges;
        for(int i=0;i<m;i++)
        {
            for(int j=0;j<n;j++)
            {
                if(i+1<m) edges.push_back(Edge(i*n+j,(i+1)*n+j,abs(heights[i][j]-heights[i+1][j])));
                if(j+1<n) edges.push_back(Edge(i*n+j,i*n+j+1,abs(heights[i][j]-heights[i][j+1])));
            }
        }
        sort(edges.begin(),edges.end(),cmp);
        Djset ds(m*n);
        int cost=0;
        for(auto e:edges)
        {
            cost=e.dis;
            ds.merge(e.u,e.v);
            if(ds.issame(0,m*n-1)) break;
        }
        return cost;
    }
};

二分+BFS:

class Solution {
public:
    int dis[4][2]={{-1,0},{1,0},{0,-1},{0,1}};
    bool findfun(vector<vector<int>>& heights,int d)
    {
        int m=heights.size(),n=heights[0].size();
        vector<bool> vis(m*n);
        queue<int> q;
        q.push(0);
        while(!q.empty())
        {
            int cur=q.front(); q.pop();
            if(vis[cur]) continue;
            vis[cur]=true;
            int r=cur/n,c=cur%n;
            for(int i=0;i<4;i++)
            {
                int nr=r+dis[i][0];
                int nc=c+dis[i][1];
                if(nr>=m || nr<0 || nc>=n || nc<0 || vis[nr*n+nc] || abs(heights[r][c]-heights[nr][nc])>d) continue;
                if(nr*n+nc==m*n-1) return true;
                q.push(nr*n+nc);
            }
        }
        return false;
    }
    int minimumEffortPath(vector<vector<int>>& heights) {
        int l=0,r=1e6;
        int cost=0;
        while(l<=r)
        {
            int mid=l+(r-l)/2;
            if(findfun(heights,mid))
            {
                r=mid-1;
                cost=mid;
            }
            else
            {
                l=mid+1;
            }
        }
        return cost;
    }
};

BFS + DP

class Solution {
public:
    int dis[4][2]={{-1,0},{1,0},{0,-1},{0,1}};
    int minimumEffortPath(vector<vector<int>>& heights) {
        int m = heights.size(),n = heights[0].size();
        // 记录到起点到达该点的最小消耗体力
        vector<vector<int>> dp(m,vector<int>(n,1e6));
        dp[0][0]=0;
        queue<int> q;
        q.push(0);
        while(!q.empty())
        {
            int cur=q.front(); q.pop();
            int r=cur/n;
            int c=cur%n;
            for(int i=0;i<4;i++)
            {
                int nr=r+dis[i][0];
                int nc=c+dis[i][1];
                if(nr>=0 && nr<m && nc>=0 && nc<n)
                {
                    int tmp=max(dp[r][c],abs(heights[r][c]-heights[nr][nc]));
                    if(tmp>=dp[nr][nc]) continue;
                    dp[nr][nc]=tmp;
                    q.push(nr*n+nc);
                }
            }
        }
        return dp[m-1][n-1];
    }
};
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值