题意:
有n个反面朝上的硬币,每次可以选a个硬币扔,要扔m次,目的是尽可能得让正面朝上的硬币多。问硬币正面朝上的期望为多少。
思路:
题目又看错了…主要是样例手算不出来…就以为本来的理解是对的…
事实上它是有贪心在里面的,因为尽可能要让正面朝上的硬币多,所以每次尽可能扔反面朝上的硬币,如果反面朝上的硬币不足a个的话,把反面朝上的硬币全选了以外正面朝上的硬币也选几个。
这里就可以dp了。
。
对于某个状态,再扔一次a个硬币中有l个硬币正面朝上的概率为。
当反面朝上的硬币大于等于a个的话,有转移,其中,表示这次扔正面朝上的硬币数。
当反面朝上的硬币小于a个的话,有转移,其中。
边界条件为。
再算一下期望就可以了。
代码:
double dp[110][110];//扔i次有j面朝上的概率
double c[110][110],xs[110];
void init()
{
c[0][0]=1;
for(int i=1;i<=100;i++)//j是上面,i是下面
{
c[i][0]=1;
for(int j=1;j<=i;j++)
{
c[i][j]=c[i-1][j]+c[i-1][j-1];
}
}
xs[1]=0.5;
for(int i=2;i<=100;i++)
xs[i]=0.5*xs[i-1];
}
int main()
{
int t,n,m,a;
init();
scanf("%d",&t);
while(t--)
{
scanf("%d%d%d",&n,&m,&a);//n个硬币扔m次每次扔a个
memset(dp,0,sizeof(dp));
dp[0][0]=1;
for(int i=0;i<m;i++)
{
for(int j=0;j<=n;j++)
{
for(int k=0;k<=a;k++)//有k枚硬币向上
{
if(n-j>=a)dp[i+1][j+k]+=dp[i][j]*c[a][k]*xs[a];
else dp[i+1][j-(a-n+j)+k]+=dp[i][j]*c[a][k]*xs[a];
}
}
}
/*for(int i=1;i<=m;i++)
{
for(int j=0;j<=n;j++)
printf("%.3f ",dp[i][j]);
printf("\n");
}*/
double ans=0;
for(int i=0;i<=n;i++)
ans+=dp[m][i]*i;
printf("%.3f\n",ans);
}
return 0;
}
本博客所有文章除特别声明外,均采用 CC BY-SA 4.0 协议 ,转载请注明出处!