leetcode面试题60. n个骰子的点数

目录

  • 题目来源
  • 解题方法
    • 动态规划

题目来源

leetcode面试题60. n个骰子的点数_第1张图片

解题方法

动态规划

思路描述,n 枚骰子掷出的点数的范围是 [n, 6*n],也就是最后数组的长度为 5n + 1,因为每个骰子掷出每个数字的概率都是 1/6,所以对于 n 枚骰子,每次掷出的数字组合的概率都为 (1/6)^n。
这题就可以转化为加起来能达到的目标数字组合有几种。例如2个骰子需要投出4,那就有(1,3)(2,2)(3,1)三种情况,而每种情况都是(1/6)(1/6),因此概率为3(1/6)^2
第j个骰子的时候,结果应该加上第j-1个骰子的值,例如dp(2,4)应该加上dp(1,1),因为只要第二轮投一个3即可,加上dp(1,2),因为只要第二轮投一个2即可,加上dp(1,3),因为只要第二轮投一个1即可
附上代码

class Solution {
public:
    vector twoSum(int n) {
        vector ans;
        int dp[n+1][6*n+1];
        memset(dp,0,sizeof(dp));
        // i:第i枚骰子,j:掷出的点数
        for(int i=1; i<=n;i++)
            for(int j=i;j<=6*i;j++){
                if(i==1){
                    dp[i][j]=1;
                    continue;
                }
                // k:骰子点数1-6
                for(int k=1;k<=6;k++){
                    if(j-k>=i-1)
                        dp[i][j]+=dp[i-1][j-k];
                }
            }
        for(int i=n;i<=6*n;i++){
            ans.push_back(dp[n][i]*pow(1.0/6,n));
        }
        return ans;
    }
};

空间优化(2维度->1维度)

class Solution {
public:
    vector twoSum(int n) {
        vector ans;
        int dp[6*n+1];
        memset(dp,0,sizeof(dp));
        // i:第i枚骰子,j:掷出的点数
        for(int i=1; i<=n;i++)
            for(int j=6*i;j>=i;j--){
                dp[j]=0;
                if(i==1){
                    dp[j]=1;
                    continue;
                }
                for(int k=1;k<=6;k++){
                    if(j-k>=i-1)
                        dp[j]+=dp[j-k];
                }
            }
        for(int i=n;i<=6*n;i++){
            ans.push_back(dp[i]*pow(1.0/6,n));
        }
        return ans;
    }
};

你可能感兴趣的:(leetcode刷题之路,动态规划,算法)