Leetcode 1514 概率最大的路径

1. 题目描述

原题链接:Leetcode 1514 概率最大的路径

给你一个由 n 个节点(下标从 0 开始)组成的无向加权图,该图由一个描述边的列表组成,其中 edges[i] = [a, b] 表示连接节点 ab 的一条无向边,且该边遍历成功的概率为 succProb[i]

指定两个节点分别作为起点 start 和终点 end ,请你找出从起点到终点成功概率最大的路径,并返回其成功概率。

如果不存在从 startend 的路径,请 返回 0 。只要答案与标准答案的误差不超过 1e-5 ,就会被视作正确答案。

在这里插入图片描述

2. 我的尝试

该题本质上是一个单源汇最短路问题。每条边的长度就是该边遍历成功的概率,两点之间的路径长度就等于该路径上各边概率的乘积。这样,求 startend 的最大概率就相当于求 startend 的最短路。题目保证了各边概率不超过1,相当于保证了无负权值的边

求解单源汇无负权值的最短路问题,可以使用dijkstra算法。本题中节点个数 n 和边的个数 m 的范围分别是 2 ≤ n ≤ 1 0 4 2 \leq n \leq10^4 2n104 0 ≤ m ≤ 2 ∗ 1 0 4 0 \leq m \leq 2*10^4 0m2104 ,即节点个数与边的个数数量级相当,为稀疏图,因此考虑使用堆优化版本的dijkstra算法。时间复杂度为 O ( m × l o g ( n ) ) O(m \times log(n)) O(m×log(n))

const int N = 1e4 + 10;
const int M = 4e4 + 10;

class Solution {
public:
    int h[N], e[M], ne[M], idx;
    double w[M], d[N];
    bool st[N];
    priority_queue<pair<double, int>> heap;

    void add(int a, int b, double c) {
        e[idx] = b;
        w[idx] = c;
        ne[idx] = h[a];
        h[a] = idx ++;
    }

    double dijkstra(int start, int end) {
        for (int i = 0; i < end; i ++) d[i] = 0;

        d[start] = 1;
        heap.push({1, start});

        while (heap.size()) {
            auto t = heap.top();
            heap.pop();

            double dist = t.first;
            int ver = t.second;

            if (st[ver]) continue;
            st[ver] = true;

            for (int i = h[ver]; i != -1; i = ne[i]) {
                int j = e[i];
                if (d[j] < d[ver] * w[i]) {
                    d[j] = d[ver] * w[i];
                    heap.push({d[j], j});
                }
            }
        }

        return d[end];
    }

    double maxProbability(int n, vector<vector<int>>& edges, vector<double>& succProb, int start_node, int end_node) {
        int m = edges.size();
        memset(h, -1, sizeof h);

        for (int i = 0; i < m; i++) {
            int a = edges[i][0], b = edges[i][1];
            double c = succProb[i];
            add(a, b, c);
            add(b, a, c);
        }

        return dijkstra(start_node, end_node);
    }
};

在这里插入图片描述

  • 18
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
好的,我可以帮你解答这个问题。 题目描述: 给定一个 n x n 的网格,每个单元格都有一个正整数,代表从该点出发的初始能量。你的初始位置是左上角,即 (0,0) ,目标位置是右下角,即 (n-1,n-1)。你只能向右或向下走。在你走过某个单元格时,你需要用掉那个单元格中的能量(即:如果你在单元格(i,j)上,那么你需要用掉 grid[i][j] 的能量)。如果你没有足够的能量,那么你不能继续前进。你的目标是在保持最小初始能量的情况下,找到一条从左上角到右下角的路径,使得沿路径所需的能量最小化。 注意:当你经过某个单元格时,你需要跟踪你通过该单元格所剩余的能量(如果剩余能量为正数,则保留,否则将其归零)。 解题思路: 本题可以使用动态规划来解决。我们定义 dp[i][j] 表示从左上角到 (i, j) 位置所需要的最小初始能量。显然,dp[0][0] = grid[0][0]。 对于第一行和第一列,由于我们只能向右或向下走,因此我们可以得到: dp[0][j] = max(dp[0][j-1], grid[0][j]) dp[i][0] = max(dp[i-1][0], grid[i][0]) 对于其他位置,我们可以通过向右或向下移动到达该位置。因此,我们可以得到: dp[i][j] = min(max(dp[i-1][j], dp[i][j-1]) - grid[i][j], 0) + grid[i][j] 由于最终状态是 dp[n-1][n-1],因此我们可以得到最终的答案为 max(dp[n-1][n-1], 1)。 代码实现: ```c int calculateMinimumHP(int** dungeon, int dungeonSize, int* dungeonColSize){ int m = dungeonSize, n = dungeonColSize[0]; int dp[m][n]; dp[0][0] = dungeon[0][0]; for (int j = 1; j < n; j++) { dp[0][j] = max(dp[0][j-1], dungeon[0][j]); } for (int i = 1; i < m; i++) { dp[i][0] = max(dp[i-1][0], dungeon[i][0]); } for (int i = 1; i < m; i++) { for (int j = 1; j < n; j++) { dp[i][j] = min(max(dp[i-1][j], dp[i][j-1]) - dungeon[i][j], 0) + dungeon[i][j]; } } return max(dp[m-1][n-1], 1); } ``` 这就是使用完整的c语言完成leetcode1514题的代码实现。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值