【LeetCode(Java) - 1230】抛掷硬币

1、题目描述

在这里插入图片描述

2、解题思路

  本题是和背包问题很像的动态规划题型。

  题目要求是给定 n 个硬币,求 target 个硬币朝上的概率。

  设 dp[i][j] 表示前 i 个硬币中,有 j 个硬币朝上的概率,于是最终结果返回 dp[n][target] 即可。

  前 i 个硬币即:0、1、2、…、i-1

  dp[i][j] 会有哪些状态呢?

  对于前 i 个硬币的最后一枚硬币,即第 i-1 枚硬币,它有两种状态:朝上或者朝下。

  1、第 i-1 枚硬币是朝上的,那么问题就转化为前 i-1 个硬币中,有 j-1 个硬币朝上的概率。此时,dp[i][j] = dp[i-1][j-1] × prob[i-1]

  2、第 i-1 枚硬币是朝下的,那么问题就转化为:前 i-1 个硬币中,有 j 个硬币朝上的概率,此时 dp[i][j] = dp[i-1][j] × (1 - prob[i-1])

  显然,两种情况都是可能的,因此状态转移方程为:

  dp[i][j] = dp[i-1][j-1] × prob[i-1] + dp[i-1][j] × (1 - prob[i-1])

  可以看到,每一个状态都和 dp[i-1][…] 有关,可以进行优化。

3、解题代码

class Solution {
    
    
    public double probabilityOfHeads(double[] prob, int target) {
    
    
        int n = prob.length;
        // dp[i][j] 表示前 i 个硬币中,j 个硬币朝上的概率
        double[][] dp = new double[n + 1][target + 1];
        // “一个硬币都没有,一个朝上的都没” 是确定事件,因此概率为 1
        dp[0][0] = 1.0;
        for (int i = 1; i <= n; i++) {
    
    
            // 给定的硬币全朝下
            dp[i][0] = dp[i - 1][0] * (1 - prob[i - 1]);
        }
        for (int i = 1; i <= n; i++) {
    
    
            for (int j = 1; j <= target; j++) {
    
    
                dp[i][j] = dp[i-1][j] * (1 - prob[i-1]) + dp[i-1][j-1] * prob[i-1];
            }
        }
        return dp[n][target];
    }
}

猜你喜欢

转载自blog.csdn.net/qq_29051413/article/details/108559944