【剑指Offer】n个骰子的点数

题目

把n个骰子扔在地上,所有骰子朝上一面的点数之和为s。输入n,打印出s的所有可能的值出现的概率。

你需要用一个浮点数数组返回答案,其中第 i 个元素代表这 n 个骰子所能掷出的点数集合中第 i 小的那个的概率。

思路

初见就没弄懂题目什么意思,看题解也不是很明白,后来自己弄懂了。

首先,n 枚骰子掷出的点数的范围是 [n, 6*n],根据排列组合,所有投掷的总可能性是6^n

这道题可以使用DP

分解状态时,我们理解为每一次投掷一个骰子,然后把之前的结果加起来,用二维数组保存之前的状态,就可以避免递归重复计算的问题,降低时间复杂度。

以下数组格子里是出现次数可能的编号,而不是出现次数

第一次

123456

第二次

123456      
123456789101112

这就可以解释代码中的

这个部分的作用

更具体的解释见书上294页或题解:https://leetcode-cn.com/problems/nge-tou-zi-de-dian-shu-lcof/solution/nge-tou-zi-de-dian-shu-dong-tai-gui-hua-ji-qi-yo-3/

代码

class Solution {
public:
    vector<double> twoSum(int n) {
        vector<double> ret;
        int dp[15][70]; //n<=11 最大6*11=66

        memset(dp, 0, sizeof(dp));

        //初始状态设置好,第一个骰子,六个面,每个面出现的次数为1
        for (int i = 1; i <= 6; i ++) {
            dp[1][i] = 1;
        }


        for (int i = 2; i <= n; i ++) {
            for (int j = i; j <= 6*i; j ++) {
                for (int cur = 1; cur <= 6; cur ++) {
                    if (j - cur <= 0) {
                        break;
                    }
                    dp[i][j] += dp[i-1][j-cur];
                }
            }
        }

        //总数是6^n
        int all = pow(6, n);
        
        for (int i = n; i <= 6 * n; i ++) {
            ret.push_back(dp[n][i] * 1.0 / all);
        }
        return ret;

    }
};

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值