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])
扫描二维码关注公众号,回复:
11697581 查看本文章
显然,两种情况都是可能的,因此状态转移方程为:
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];
}
}