zoukankan      html  css  js  c++  java
  • ACM-ICPC 2017 Asia Urumqi:A. Coins(DP) 组合数学

    Alice and Bob are playing a simple game. They line up a row of nn identical coins, all with the heads facing down onto the table and the tails upward.

    For exactly mm times they select any kk 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.

    Input

    The input has several test cases and the first line contains the integer t (1 le t le 1000)t(1t1000) which is the total number of cases.

    For each case, a line contains three space-separated integers nn, m (1 le n, m le 100)m(1n,m100)and k (1 le k le n)k(1kn).

    Output

    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 33 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

    题目来源

    ACM-ICPC 2017 Asia Urumqi

     

    题意:有n枚朝下的硬币,我们可以投掷这些硬币m次,每次投掷 t 枚硬币,问最后朝上硬币的期望

    分析:最优的策略一定是:当有至少 k 枚硬币面朝下时,则选 k 枚面朝下的硬币去抛掷(任意k 枚都可以);如果不足 k 枚面朝下,则在选择所有面朝下的硬币的基础上再额外选择若干面朝上的硬币。

                于是有动态规划,记 dp[i][j]表示抛掷了 i 次后,有 j 枚硬币面朝上的概率。他们应该满足dp[i][0]+dp[i][1]+...+dp[i][n]=1。转移时,考虑从当前状态(i,j)出发,抛掷的 k 枚硬币的所有可能结果:分别有 0~k 枚面朝上。其中 k 枚硬币抛掷后有 l 枚面朝上的概率为 C(k,l)/2k。时间复杂度 O(nmk)。

    参考博客:https://blog.csdn.net/mitsuha_/article/details/79307065

    AC代码:

    #include <map>
    #include <set>
    #include <stack>
    #include <cmath>
    #include <queue>
    #include <cstdio>
    #include <vector>
    #include <string>
    #include <cstring>
    #include <iomanip>
    #include <iostream>
    #include <algorithm>
    #define ls (r<<1)
    #define rs (r<<1|1)
    #define debug(a) cout << #a << " " << a << endl
    using namespace std;
    typedef long long ll;
    const ll maxn = 205;
    const ll mod = 1e9 + 7;
    double dp[maxn][maxn], p[maxn], c[maxn][maxn];
    int main() {
        ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
        c[0][0] = 1;
        for( ll i = 1; i <= 100; i ++ ) {
            c[i][0] = 1;
            for( ll j = 1; j <= i; j ++ ) {
                c[i][j] = c[i-1][j-1] + c[i-1][j];  //打表前一百个的组合数
            }
        }
        p[0] = 1;
        for( ll i = 1; i <= 100; i ++ ) {
            p[i] = p[i-1]/2;   //几枚硬币朝上的概率
        }
        ll T;
        cin >> T;
        while( T -- ) {
            ll n, m, t;
            cin >> n >> m >> t;
            memset( dp, 0, sizeof(dp) );
            dp[0][0] = 1;   //记录投掷i次有j枚硬币朝上的概率
            for( ll i = 0; i < m; i ++ ) {
                for( ll j = 0; j <= n; j ++ ) {
                    if( dp[i][j] == 0 ) {
                        continue;
                    }
                    for( ll k = 0; k <= t; k ++ ) {
                        if( n-j >= t ) {   //还有硬币没有朝上的情况
                            dp[i+1][j+k] += dp[i][j]*c[t][k]*p[t];
                        } else {   //已经有n枚硬币朝上了还得投掷的情况,这时会使n枚变少或者不变
                            dp[i+1][n-t+k] += dp[i][j]*c[t][k]*p[t];  //n-t代表会改变t枚硬币的情况,k代表改变的情况朝上的情况
                        }
                    }
                }
            }
            double ans = 0;
            for( ll i = 1; i <= n; i ++ ) {
                ans += dp[m][i]*i;       //计算期望
            }
            printf("%.3lf
    ",ans);
        }
        return 0;
    }
    

      

    彼时当年少,莫负好时光。
  • 相关阅读:
    mysql8.0 一次性备份导出/导入恢复所有数据库
    访问服务器共享资源不需要输帐号和密码
    win7 系统 提示用户'sa'登录失败
    Adoquery.disablecontrols和enablecontrols
    DBGridEh 导出数据到EXCEL文件
    Microsoft SQL Server 2005资料库(数据库)卸载方法
    64位操作系统下创建组件失败的解决办法
    U盘中的文件为什么看不见?
    解决错误提示unable to invoke code completion due to errors in source cord.
    浪潮服务器Windows Server系统异常断电导致系统中CentOS7虚拟机系统崩溃无法正常启动grub2故障修复error: relocation 0x48 is not implemented yet
  • 原文地址:https://www.cnblogs.com/l609929321/p/9387663.html
Copyright © 2011-2022 走看看