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

思路

第一步:定义数组元素的含义
dp[i][j],表示投掷完i枚骰子后,点数j的出现次数

第二步:找出关系数组元素间的关系式
最后一个阶段也就是投掷完 n 枚骰子后的这个阶段,我们用dp[n][j] 来表示最后一个阶段点数 j 出现的次数。
单单看第 n 枚骰子,它的点数可能为 1 , 2, 3, ... , 6 ,因此投掷完 n 枚骰子后点数 j 出现的次数,可以由投掷完 n-1 枚骰子后,对应点数 j-1, j-2, j-3, ... , j-6 出现的次数之和转化过来。因此,第i枚骰子投掷后,出现的分数j的状态转移可以写成dp[i][j] += dp[i-1][j-cur];

第三步:初始状态

我们可以直接知道的状态是啥,就是第一阶段的状态:投掷完 1 枚骰子后,它的可能点数分别为 1, 2, 3, ... , 6并且每个点数出现的次数都是 1.

for (int i = 1; i <= 6; i ++) {
    dp[1][i] = 1;
}

代码

class Solution {
public:
    vector<double> twoSum(int n) {
        int dp[12][67];//表示投掷完i枚骰子,各个点出现的次数
        memset(dp, 0, sizeof(dp));//全部初始化为0
        for (int i = 1; i <= 6; i++) {
            dp[1][i] = 1;//初始值,第1枚骰子的各值出现次数为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];
                }
            }
        }
        int all = pow(6, n);//总次数
        vector<double> ret;
        for (int i = n; i <= 6 * n; i++) {
            ret.push_back((double)dp[n][i] / all);
        }
        return ret;
    }
};

你可能感兴趣的:(【魂】算法,leetcode,动态规划)