思路
第一步:定义数组元素的含义
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;
}
};