《剑指Offer》-60-n 个骰子的点数
打印出 n 个骰子所能扔出的所有点数的概率
思路
dp[i][j] 表示 i 个骰子,投出 j 的概率
而概率 = 点数出现的次数 / 总次数
而 i 个骰子掷出 j 的次数 = i - 1 个骰子掷出 j- 1 的次数 + i - 1 个骰子掷出 j -2 的次数 + … + i - 1 个骰子掷出 j -6 的次数,因为这个单独的骰子能掷出这 6 种结果,这里的 j - n 必须大于1
于是比如dp[2][3] = (dp[1][2]+dp[1][1])/6^2
vector<double> dicesProbability(int n) { // dp[i][j]表示i个骰子掷出j的概率 vector<vector<double>> dp(n+1, vector<double>(6*n+1,0)); vector<double> res; // 那么我们要得到的就是dp[n][n]到dp[n][6n] // 如果转化为一个矩阵,那么整个右上角和左下角都是不要的 // 初始化 for (int i = 1; i <= 6; i++) dp[1][i] = 1.0 / pow(6,n); for (int i = 2; i <= n; i++) { for (int j = i; j <= 6*i; j++) { int k = j-1; while (k >= 1 && k>=j-6) { dp[i][j] += dp[i - 1][k]; k--; } } } for (int i = n; i <= 6 * n; i++) res.push_back(dp[n][i]); return res; }
这是我想出最直观地做法,从 1 个骰子地所有情况开始向上递推,但是很明显套了三层循环,而且用了二维数组,时间和空间效率肯定都不好看,还好题目最大 n 也就 11,所以就接过来说还是看得下去的,但是肯定不能让面试官满意
这里的时间和空间复杂的其实是可以算出来的,3n(n+1)的时间复杂度和6n2的空间复杂度
通常二维动态规划都可以优化为一维,这里也不例外,每一层其实都只依赖上一层,但是……考虑到覆盖的情况也不能一个数组就搞定了吧
尝试优化为两个数组
vector<double> dicesProbability(int n) { vector<double> dp1(6*n+1,0),dp2(6*n+1,0); vector<double> res; // 这里为什么这么初始化呢?这一行代表了每个最小可能性点数单次的概率 for (int i = 1; i <= 6; i++) dp1[i] = 1.0 / pow(6,n); for (int i = 2; i <= n; i++) { for (int j = i; j <= 6*i; j++) { int k = j - 1; while (k >= 0 && k >= j - 6) { if (i & 1) dp1[j] += dp2[k]; else dp2[j] += dp1[k]; k--; } } // 将另一个数组重置,用于下一次 if (i & 1) dp2.assign(dp2.size(), 0); else dp1.assign(dp1.size(), 0); } for (int i = n; i <= 6 * n; i++) { if (n & 1)res.push_back(dp1[i]); else res.push_back(dp2[i]); } return res; }
这是第一版的修改代码,但是其实可以让一个数组始终更新,并将结果赋值给另一个数组保存上一轮结果,
这样可以避免以上所有的三处判断
vector<double> dicesProbability(int n) { vector<double> dp(6 * n + 1, 0), temp(6 * n + 1, 0); vector<double> res; for (int i = 1; i <= 6; i++) dp[i] = 1.0 / pow(6, n); for (int i = 2; i <= n; i++) { for (int j = i; j <= 6 * i; j++) { int k = j - 1; while (k >= 0 && k >= j - 6) { temp[j] += dp[k]; k--; } } dp = temp; temp.assign(temp.size(), 0);// 仍旧要清空 } for (int i = n; i <= 6 * n; i++) res.push_back(dp[i]); return res; }
本文作者:YaosGHC
本文链接:https://www.cnblogs.com/yaocy/p/17622373.html
版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步