lintcode-20-骰子求和
20-骰子求和
扔 n 个骰子,向上面的数字之和为 S。给定 Given n,请列出所有可能的 S 值及其相应的概率。
注意事项
You do not care about the accuracy of the result, we will help you to output results.
样例
给定 n = 1,返回 [ [1, 0.17], [2, 0.17], [3, 0.17], [4, 0.17], [5, 0.17], [6, 0.17]]。
标签
数学 动态规划 概率
思路
利用动态规划,用二维数组 dp[i][j] 表示 i 颗骰子所能掷出点数为 j 的次数。
- 初始时只有一颗骰子,此时 dp[1][j] = 0,(1 <= j <= 6)
- 加一颗骰子后,此时 2 颗骰子所能掷出的点数为 2 到 12,此时投掷的结果与上一次投掷的结果相关,若 2 颗骰子投出 j 点,则要求第 1 颗投掷投出 k 点且第 2 颗投出 j - k 点(j > k) ,例如 dp[2][2] = dp[1][1],dp[2][3] = dp[1][1] + dp[1][2]...
- 一般化,加至第 i 颗骰子后,此时 i 颗骰子所能掷出的点数为 i 到 6 * 1,此时投掷的结果与前 i - 1次投掷的结果相关,若 i 颗骰子投出 j 点,则要求前 i - 1 颗投掷投出 k 点且第 2 颗投出 j - k点(j > k) ,即 dp[i][j] = dp[i-1][j-1] + dp[i-1][j-2] + dp[i-1][j-3] + dp[i-1][j-4] + dp[i-1][j-5] + dp[i-1][j-6]
最后某点的次数除以总数,即投掷出此点的概率。
code
class Solution {
public:
/**
* @param n an integer
* @return a list of pair<sum, probability>
*/
vector<pair<int, double>> dicesSum(int n) {
// Write your code here
if (n <= 0) {
return vector<pair<int, double> >();
}
long long total = powOf6(n);
vector<vector<long long>> dp(n + 1, vector<long long>(6 * n + 1, 0));
dp[1][1] = 1;
dp[1][2] = 1;
dp[1][3] = 1;
dp[1][4] = 1;
dp[1][5] = 1;
dp[1][6] = 1;
for (int i = 2; i <= n; i++) {
for (int j = i; j <= i * 6; j++) {
long x1 = 0, x2 = 0, x3 = 0, x4 = 0, x5 = 0, x6 = 0;
if (j - 1 > 0) {
x1 = dp[i - 1][j - 1];
}
if (j - 2 > 0) {
x2 = dp[i - 1][j - 2];
}
if (j - 3 > 0) {
x3 = dp[i - 1][j - 3];
}
if (j - 4 > 0) {
x4 = dp[i - 1][j - 4];
}
if (j - 5 > 0) {
x5 = dp[i - 1][j - 5];
}
if (j - 6 > 0) {
x6 = dp[i - 1][j - 6];
}
dp[i][j] = x1 + x2 + x3 + x4 + x5 + x6;
}
}
vector<pair<int, double> > result;
for (int i = n; i <= 6 * n; i++) {
pair<int, double> p(i, double(dp[n][i]) / total);
result.push_back(p);
}
return result;
}
long long powOf6(int n) {
long long sum = 1;
for (int i = 0; i<n; i++) {
sum *= 6;
}
return sum;
}
};