zoukankan      html  css  js  c++  java
  • Coins I(ICPC2017 Urumqi)

    题目描述

    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
    ",ans);
        }
        return 0;
    }

  • 相关阅读:
    泛型编程 --迭代器
    cpp输入输出加速
    算法训练 加法运算(指针的一个测试)
    蓝桥杯-基础练习-字母图形
    蓝桥杯-基础练习-特殊回文数
    win10下稍微美观下Git
    mysql8.0以上版本注册驱动并建立数据库的连接公共代码
    idea使用的一些问题解决记录
    单链表逆转(递归指针实现)
    increment/decrement/dereference操作符
  • 原文地址:https://www.cnblogs.com/lemon-jade/p/9516146.html
Copyright © 2011-2022 走看看