Coins I(ICPC2017 Urumqi)

https://www.jisuanke.com/contest/1409/challenges

题目描述

Alice and Bob are playing a simple game. They line up a row of n identical coins, all with the heads facing down onto the table and the tails upward.
For exactly m times they select any k of the coins and toss them into the air, replacing each of them either heads-up or heads-down with the same possibility. Their purpose is to gain as many coins heads-up as they can.

输入

The input has several test cases and the first line contains the integer t (1 ≤ t ≤ 1000) which is the total number of cases.
For each case, a line contains three space-separated integers n, m (1 ≤ n, m ≤ 100) and k (1 ≤ k ≤ n).

输出

For each test case, output the expected number of coins heads-up which you could have at the end under the optimal strategy, as a real number with the precision of 3 digits.

样例输入

6
2 1 1
2 3 1
5 4 3
6 2 3
6 100 1
6 100 2

样例输

0.500
1.250
3.479
3.000
5.500
5.000
题意:n个反面朝上的硬币,m次抛,每次抛硬币从n个硬币中选k个,问最优情况下,正面朝上的期望
题解:显然是一道概率dp 的题,因为这道题说的是最优,很明显每次选的k枚硬币尽量都选反面朝上的
dp[i][j]表示 第i次抛硬币中j个正面朝上的概率,对于抛k枚硬币,c枚朝上的组合有 C(k,c)种
对于抛硬币正和反的概率都是0.5,所以抛k次概率为0.5^k
我们枚举抛k 枚硬币出现正面朝上的个数c,dp[i+1][x] = dp[i][j]*C(k,c)*0.5^k (x为当前状态所有硬币正面朝上的个数)

当某一状态中剩余反面朝上的个数 >= k,则 全抛反面朝上的硬币 即x = c,否则,把所有反面朝上的硬币 + 一些正面朝上的硬币 一起抛,没参与抛的正面朝上的硬币数为 n - k, 即 x = n - k + c

AC code:
#include <bits/stdc++.h>
 
using namespace std;
const int N = 100 + 10;
double dp[N][N],C[N][N],p[N];
int main()
{
    int t,n,m,k;
    scanf("%d",&t);
    C[0][0] = 1;
    p[0] = 1;
    for(int i = 1;i < N;i++)
    {
        p[i] =p[i-1]*0.5;
        for(int j = 0;j <= i;j++)
            C[i][j] = (j == 0?1:(C[i-1][j]+C[i-1][j-1]));
    }
    while(t--)
    {
        scanf("%d%d%d",&n,&m,&k);
        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 c = 0;c <= k;c++)
                {
                    if(n - j >= k)   dp[i+1][j+c] += dp[i][j]*C[k][c]*p[k];
                    else    dp[i+1][n-k+c] += dp[i][j]*C[k][c]*p[k];
                }
        double ans = 0;
        for(int i = 0;i <= n;i++)
            ans += dp[m][i]*i;
        printf("%.3lf\n",ans);
    }
    return 0;
}

 


posted @ 2018-08-22 10:29  jadelemon  阅读(297)  评论(0编辑  收藏  举报