题目大意:有n枚面朝下的硬币,问抛m次之后,最大的朝上的硬币数期望是多少?
分析:为什么问的是最大的朝上个数呢?因为是要抛m次,而算的是你最后面朝上的硬币的个数。想想看,想要最后面朝上的硬币最多,每次都选面朝下的硬币来抛,问题就在于可能出现抛了不到m次就全朝上的情况,这个时候只能选一枚面朝上的硬币来抛。
解法:看到期望就以为是期望dp了嘛?试了一下然后发现期望dp状态都列不出来。实际上这题是一个概率dp,概率dp和期望dp是相似的,用全概率公式转移,只要计算子问题的概率就行。最后期望就直接套期望公式。
转移方程:设dp[i][j]表示抛i次j个向上的概率,根据全概率公式:dp[i][j] = dp[i - 1][j] * 0.5 + dp[i - 1][j - 1] * 0.5,特别的,当j == (n - 1) 时,有dp[i][j] = dp[i - 1][j] * 0.5 + dp[i - 1][j + 1] * 0.5 + dp[i - 1][j - 1] * 0.5。
原因在于j == n - 1这个状态也可能是由已经全部朝上的硬币转移得到,可能抛了一枚已经面朝上的硬币而结果是那枚硬币面朝下了。
#include<bits/stdc++.h>
using namespace std;
const int maxn = 5e2 + 10;
double dp[maxn][maxn];
int main() {
int n,m;
scanf("%d%d",&n,&m);
dp[0][0] = 1;
for(int i = 1; i <= m; i++) {
for(int j = 0; j <= n; j++) {
dp[i][j] += dp[i - 1][j] * 0.5;
dp[i][j] += dp[i - 1][j - 1] * 0.5;
if(j == n - 1) dp[i][j] += dp[i - 1][n] * 0.5;
}
}
double ans = 0;
for(int i = 0; i <= n; i++)
ans += dp[m][i] * i;
printf("%.6lf\n",ans);
return 0;
}