抛硬币 Flipping Coins(Gym - 101606F)(DP)



题意:给出N个硬币,开始均反面朝上。每次挑出其中一个抛,连续K次,求正面朝上的最大数学期望。
----------------------------------------------------------------------------------------------------------------------

由于是求最大数学期望,所以每次抛硬币即要优先选择反面硬币

所以只有两种挑选硬币的情况:

  1.正面数量为 0 ~ n-1 ,选择反面硬币抛,抛出结果正面数量比原本 +1 或 不变

  2.正面数量为 n,只能够选择正面硬币抛,抛出结果正面数量比原本 -1 或 不变
----------------------------------------------------------------------------------------------------------------------

设 dp[i][j] 表示: 第 i 次抛硬币后, j 个硬币正面朝上的概率

  1.当 j < n 时,dp[i][j]的概率一分为二,各给dp[i+1][j]dp[i+1][j+1],即

for(int j=0;j<n;j++){
    dp[i+1][j]+=dp[i][j]/2;
    dp[i+1][j+1]+=dp[i][j]/2;
}

  2.当 j == n 时,dp[i][j]的概率一分为二,各给dp[i+1][j]dp[i+1][j-1],即

dp[i+1][n]+=dp[i][n]/2;
dp[i+1][n-1]+=dp[i][n]/2;

如此即可求出n个硬币抛k次的各个正面朝上的概率,最后求数学期望即可

附:n=2,k=4时的dp转移表格:

技术分享图片

技术分享图片
 1 #include <stdio.h>
 2 #include <math.h>
 3 #include <string.h>
 4 #include <algorithm>
 5 #include <iostream>
 6 #include <queue>
 7 #include <stack>
 8 #include <functional>
 9 #define INF 0x3f3f3f3f
10 using namespace std;
11 typedef long long ll;
12 double dp[410][410], ans;
13 int main(){
14     int n, k;
15     while (~scanf("%d %d", &n, &k)){
16         for (int i = 0; i <= 400; i++)
17             for (int j = 0; j <= 400; j++)
18                 dp[i][j] = 0;
19         dp[0][0] = 1;
20         for (int i = 0; i < k; i++){
21             for (int j = 0; j < n; j++){
22                 dp[i + 1][j] += dp[i][j] * 0.5;
23                 dp[i + 1][j + 1] += dp[i][j] * 0.5;
24             }
25             dp[i + 1][n] += dp[i][n] * 0.5;
26             dp[i + 1][n - 1] += dp[i][n] * 0.5;
27         }
28         ans = 0;
29         for (int i = 1; i <= n; i++)
30             ans += i*dp[k][i];
31         printf("%.8lf\n", ans);
32     }
33     return 0;
34 }

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值