题目

给定 n 枚硬币 (n 为奇数),编号为 1, 2, · · · , n。投掷第 i 枚硬币时有 pi 的概率正面朝上,有 1 − pi 的概率反面朝上。 设计算法求解投掷这 n 枚硬币,其中正面朝上的硬币数量多于反面朝上的概率,并分析该 算法的时间复杂度

解题

这道题使用动态规划来做。

首先创建dp[n + 1][n + 1]数组,其中dp[i][j] 表示丢了i个硬币,有j个硬币朝上,

其次,对状态进行初始化,再进行状态转移,最后返回硬币问题 - 图1

状态转移方程:硬币问题 - 图2

分析可知,时间复杂度为O(n^2)

  1. public double coin(double[] p) {
  2. int n = p.length;
  3. //dp[i][j] : 投了i个硬币有j个硬币朝上的概率
  4. double[][] dp = new double[n + 1][n + 1];
  5. Arrays.fill(dp[0], 1);
  6. dp[1][0] = 1 - p[0];
  7. dp[1][1] = p[0];
  8. for (int i = 2; i <= n; i++) {
  9. dp[i][0] = dp[i - 1][0] * (1 - p[i - 1]);
  10. for (int j = 1; j <= i; j++) {
  11. dp[i][j] = dp[i - 1][j] * (1 - p[i - 1]) + dp[i - 1][j - 1] * p[i - 1];
  12. }
  13. }
  14. double sum = 0.0;
  15. for (int i = n / 2 + 1; i <= n; i++) {
  16. sum += dp[n][i];
  17. }
  18. return sum;
  19. }