1、题目表述
总共有n个骰子,第n个骰子的的范围为1 ~ Xn,Xn表示第n个骰子的最大值,掷骰子时取所有骰子中的最大值作为本次的结果,求掷一次骰子的得到的结果的期望值。
示例:
输入: 2 2 2
输出:1.75
解释:输入的第一个2表示两个骰子,后面两个2表示两个骰子的范围都为1 ~ 2。
2、解题思路
使用动态规划来解:使用一个二维数组 dp 来保存概率值,dp [ i ] [ j ] 表示总共有 i 个骰子时,掷出的结果为 j 的概率值。计算这个二维数组的概率值时,先从第一个骰子开始计算,接着根据第一个骰子的概率值递推地计算总共有2个骰子的概率值,然后递推地计算总共3个,...... , 总共 n 个骰子的概率值。代码实现如下:
#include <iostream>
#include <vector>
#include <algorithm>
#include <stdio.h>
using namespace std;
int main()
{
int n = 2; // n表示骰子个数
int x[55] = {0, 2, 2}; // x保存每个骰子的最大点数
double dp[55][55]; // dp[i][j]表示第总共i个骰子,掷出的结果为j的概率
// 初始化动态规划数组
for (int i = 0; i <= 50; i++)
{
for (int j = 0; j <= 50; j++)
{
dp[i][j] = 0;
}
}
dp[0][0] = 1;
for (int i = 1; i <= n; i++)
{
for (int j = 1; j <= x[i]; j++)
{
double tmp = 0;
for (int k = 0; k <= j; k++)
{
tmp += dp[i-1][k];
}
dp[i][j] += tmp/x[i];
for (int k = j + 1; k <= 50; k++)
{
dp[i][k] += dp[i-1][k]/x[i];
}
}
for (int j = x[i] + 1; j <= 50; j++)
{
dp[i][j] = dp[i-1][j];
}
}
// 计算期望值
double ans = 0 ;
for (int i = 0; i <= 50; i++)
{
ans += dp[n][i] * i;
}
printf("%.2lf\n", ans);
return 0;
}