剑指 Offer 60. n个骰子的点数

题目:

剑指 Offer 60. n个骰子的点数
在这里插入图片描述

题解:

点数之和:
在这里插入图片描述
概率:
在这里插入图片描述

1. 解释一:

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

2. 解释二:

在这里插入图片描述
在这里插入图片描述

3. 疑难点:

在这里插入图片描述
在这里插入图片描述

代码:

注意:
时间复杂度:O(n * 5n * 6) == O(30 * n²), 又因为1 <= n <= 11,因此,即便是三层for循环,但最大时间复杂度也就是O(3630),也就是一共才循环3000多次,这种效率近似于线性遍历O(N),因此代码执行速度还是很快的。

public class 面试题60 {

    public static double[] twoSum(int n) {
        // 状态定义,dp[i][j]表示骰子个数为i时点数j可能出现的次数,dp[i][s]表示i个骰子掷出s点的次数
        int dp[][] = new int[n + 1][6 * n + 1];
        // 初始状态
        for(int i = 1; i <= 6; i++)
        {
            dp[1][i] = 1; // 表示一个骰子掷出i点的次数为1
        }
        for(int i = 2; i <= n; i++) // 表示骰子的个数
        {
            for(int s = i; s <= 6 * i; s++) // 表示可能会出现的点数之和
            {
                for(int j = 1; j <= 6; j++) // 表示当前这个骰子可能掷出的点数
                {
                    if(s - j < i - 1) // (总点数 s) - (当前的点数 j) >= (前i-1个骰子的最小点数之和i-1)
                    {
                        break;  // 如果不满足上述条件,则不存在这种情况,直接跳出循环即可
                    }
                    dp[i][s] += dp[i - 1][s - j]; // 当前 n 个骰子出现的点数之和等于前一次出现的点数之和加上这一次出现的点数
                }
            }
        }
        double total = Math.pow(6, n); // 掷出 n 次点数出现的所有情况
        double ans[] = new double[5 * n + 1]; // 因为最大就只会出现 5*n+1 种点数
        for(int i = n; i <= 6 * n; i++)
        {
            ans[i - n] = dp[n][i] / total; // 第i小的点数出现的概率
        }
        return ans;
    }

    public static void main(String[] args) {
        int n = 2;
        double res[] = twoSum(n);
        for(int i = 0; i < res.length; i++)
        {
            System.out.printf("%.5f  ", res[i]);
        }
        System.out.println();
    }
}

参考:

  1. 【n个骰子的点数】:详解动态规划及其优化方式
  2. 动态规划(注释清晰)
  3. 动态规划(扫了一圈,俺是最短的)
  4. C++ 动态规划解法
©️2020 CSDN 皮肤主题: 撸撸猫 设计师: 设计师小姐姐 返回首页
实付0元
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值