Gym 101606 F-Flipping Coins(概率dp)

参考博客:http://www.cnblogs.com/kang000/p/8571071.html  (这篇博客写的真的走心,ORZ)

 

题意
有n个硬币排成一排,开始的时候所有的硬币都是正面朝下,你必须要扔K次硬币,每次选择一个硬币,如果你采取最优策略,K次以后朝上的硬币数的最大期望是多少?

分析

一脸懵逼两脸懵逼三脸懵逼···

--------------------------------------------------------------------------

随机变量X是指朝上的硬币数,当有N枚硬币的时候,X=0,1,2,3....N

E(X)=1*p(1)+2*p(2)+....+n*p(n)。

要想求最大期望,我们在扔硬币的时候要遵循一个策略:尽量扔正面朝下的硬币

如果当前有0到n-1枚硬币正面朝上,我们可以选择正面朝下的硬币来扔,扔完以后朝上硬币数不变或者+1

如果当前有n枚硬币正面朝上,我们只能选择正面朝上的硬币来扔,扔完以后朝上的硬币数不变或者-1

-----------------------------------------------------------------------------------------------

令dp[i][j]为扔i次以后j枚硬币朝上的概率

根据上面总结的规律,我们可以的到状态转移方程

当j<n的时候

dp[i+1][j]+=dp[i][j]*0.5

dp[i+1][j+1]+=dp[i][j]*0.5

当j=n的时候

dp[i+1][j+1]+=dp[i][j]*0.5

dp[i+1][j-1]+=dp[i][j]*0.5

这样递推出概率来以后遍历一遍j求期望就好了~

 1 #include <cstdio>
 2 #include <cstring>
 3 #include <iostream>
 4 #include <algorithm>
 5 
 6 using namespace std;
 7 const int maxn=500;
 8 double dp[maxn][maxn];
 9 int n,k;
10 int main(){
11     scanf("%d%d",&n,&k);
12     memset(dp,0,sizeof(dp));
13     dp[0][0]=1;
14 
15     for(int i=0;i<k;i++){
16         for(int j=0;j<=n;j++){
17             if(j<n){
18                 dp[i+1][j]+=0.5*dp[i][j];
19                 dp[i+1][j+1]+=0.5*dp[i][j];
20             }
21             if(j==n){
22                 dp[i+1][j]+=0.5*dp[i][j];
23                 dp[i+1][j-1]+=0.5*dp[i][j];
24             }
25         }
26     }
27     /*for(int i=0;i<=k;i++){
28         for(int j=0;j<=n;j++){
29             printf("%d %d %f\n",i,j,dp[i][j]);
30         }
31     }*/
32    double ans=0;
33    for(int i=1;i<=n;i++){
34     ans+=dp[k][i]*i;
35    }
36    printf("%.6f",ans);
37 
38 return 0;
39 }
View Code

 

posted @ 2018-04-19 23:18  蒟蒻LQL  阅读(476)  评论(0编辑  收藏  举报