剑指 Offer 60. n个骰子的点数
从递归到动递推
记忆化搜索
最后一个数据点混不过去,会超时
class Solution {
public:
int dfs(vector<vector<int>> &f, int n, int s) {
if (s < 0) return 0;
if (n == 0) return !s;
if (f[n][s] != 0) return f[n][s];
int res = 0;
for (int i = 1; i <= 6; i ++ ) res += dfs(f, n - 1, s - i);
f[n][s] = res;
return res;
}
vector<double> dicesProbability(int n) {
vector<double> res(5 * n + 1);
vector<vector<int>> f(n + 1, vector<int>(6 * n + 1, 0));
memset(f, 0, sizeof f);
double tol = pow(6.0, n);
for (int i = n, j = 0; i <= 6 * n; i ++ , j ++ ) res[j] = dfs(f, n, i) / tol;
return res;
}
};
递推
由递归的思路得出递推式如下:
dp[i, j]:i个投子投的j的方案数;dp[i, j] = SUM(dp[i - 1, j - k]),k是1-6且j - k >= 0
class Solution {
public:
vector<double> dicesProbability(int n) {
vector<double> res(5 * n + 1);
vector<vector<int>> dp(n + 1, vector<int>(6 * n + 1, 0));
dp[0][0] = 1;
for (int i = 1; i <= n; i ++ ) {
for (int j = 1; j <= 6 * i; j ++ ) {
int sum = 0;
for (int k = 1; k <= 6; k ++ ) {
if (j - k < 0) break;
sum += dp[i - 1][j - k];
}
dp[i][j] = sum;
}
}
double tol = pow(6.0, n);
for (int i = n, j = 0; i <= 6 * n; i ++ , j ++ ) res[j] = dp[n][i] / tol;
return res;
}
};