剑指 offer 第二版:n 个骰子的点数

题目链接:https://leetcode-cn.com/problems/nge-tou-zi-de-dian-shu-lcof

思路:

首先可以确定,暴力很难过这个题。

我们假设:对于某点数 x,这 n 个骰子可以有 y 种方案数来形成。

那么每种 x 点数的出现概率其实是: y ∗ ( 1 / 6 ) n y * (1/6)^n y(1/6)n

所以我们要做的就是计算出每种点数的 y。

我们可以用 dp 来解决这个问题

d p [ i ] [ j ] dp[i][j] dp[i][j] 表示使用 i i i 个骰子,形成点数和为 j j j 的方案数

那么状态转移方程: d p [ i ] [ j ] + = d p [ i − 1 ] [ j ] + d p [ i − 1 ] [ j − w [ k ] ] dp[i][j] += dp[i - 1][j] + dp[i - 1][j - w[k]] dp[i][j]+=dp[i1][j]+dp[i1][jw[k]],其中 w [ k ] w[k] w[k] 就是点数,显然是 1 ~ 6.

但是我们知道,骰子是没有点数 0 的,

所以上状态转移方程就变成了 d p [ i ] [ j ] + = d p [ i − 1 ] [ j − w [ k ] ] dp[i][j] += dp[i - 1][j - w[k]] dp[i][j]+=dp[i1][jw[k]]

Code:

class Solution {
     
public:
    vector<double> twoSum(int n) {
     
        double base = 1.000;
        for(int i = 1;i <= n;++ i) base *= 1.0 / 6;
        memset(dp,0,sizeof(dp));
        dp[0][0] = 1;
        for(int i = 1;i <= n;++ i) {
     
            for(int j = 1;j <= 6 * n;++ j) {
     
                for(int k = 1;k <= 6;++ k) {
     
                    if(j >= k) dp[i][j] += dp[i - 1][j - k];
                }
            }
        }
        vector<double> v;
        for(int i = n;i <= 6 * n;++ i) {
     
            v.push_back(dp[n][i] * base);
        }
        return v;
    }
    int dp[15][110];
};

你可能感兴趣的:(剑指offer系列题解)