zoukankan      html  css  js  c++  java
  • P2059 [JLOI2013]卡牌游戏

    传送门

    期望DP

    刚开始想的就是DP

    设 f [ i ] [ j ] 表示已经进行了 i 轮,庄家为 j

    但是发现好像转不了...

    不知道哪些人被踢出去了...

    看一下数据,好像搞不了状压

    那么换种思路

    从 结束状态 往 开始状态 推

    不需要知道具体哪个人是庄家,只要知道与庄家相对位置为 x 时的获胜概率

    好像可以...

    设 f [ i ][ j ] 表示还剩 i 个人,从庄家开始顺时针数第 j 个人获胜的概率

    显然 f [ 1 ] [ 1 ] = 1.0,如果能递推,那么第 i 个人获胜的概率就是 f [ n ] [ i ]

    考虑转移

    肯定要枚举牌 p[ ]

    如果摸到 p[ k ],那么第 p[ k ] 个人要被踢出

    所以除了第 p[ k ] 个人以外,其他人都可以从上一层对应的位置得到一些胜率

    但是要注意摸到 p[ k ] 的概率只有 1/m ,所以得到的胜率也要 * (1/m)

    然后就可以转移了

    具体还是看代码吧

    #include<iostream>
    #include<cstdio>
    #include<algorithm>
    #include<cstring>
    #include<cmath>
    using namespace std;
    int n,m,p[57];
    double f[57][57];
    int main()
    {
        cin>>n>>m;
        for(int i=1;i<=m;i++) cin>>p[i];
    
        f[1][1]=1.0;
        for(int i=2;i<=n;i++)
            for(int k=1;k<=m;k++)
            {
                int t= ( !(p[k]%i) ) ? i : (p[k]%i); //这是被踢出的人的位置
                t++;
                for(int j=1;j<i;j++)//上一层的 j 对应这一层的 t
                {
                    if(t>i) t=1;//回到开头
                    f[i][t] += f[i-1][j]/double(m);//转移胜率
                    t++;//下一个人
                }
            }
    
        for(int i=1;i<=n;i++)
            printf("%.2lf%% ",f[n][i]*100.0);
        return 0;
    }
  • 相关阅读:
    思考
    创建Windows Mobile上兼容性好的UI 程序
    中文乱码(二)
    中文乱码(三)
    MySQL字符集产生乱码的简单讲解
    MySql乱码解决(五)
    中文乱码(四)
    mysql中文问题全处理
    Linux 中 x86 的内联汇编
    arm下的gcc内联汇编
  • 原文地址:https://www.cnblogs.com/LLTYYC/p/9596604.html
Copyright © 2011-2022 走看看