• Luogu2059 卡牌游戏-概率DP


    蒟蒻的第一道概率DP。。

    先讲一下我最开始yy的一个算法吧:

    我们设f[i][j]表示当前进行了i轮,第j个人坐庄的概率是多少。

    为什么这么想呢,因为进行了到第n轮后最后一个人必然是庄,同时这就是它的获胜的概率是吧。

    可以发现转移也是很好想的。f[i][j]=f[i-1][last]/m 。 但是

    嗯嗯,last怎么求,好像求不出啊。。所以就挂了??唉。。

    但是这也是很有启发性的,

    我们发现这样搞不出的原因是:它的淘汰的是围绕着庄转一定步数后的数。

    而我们无法维护哪些已经被淘汰,所以我们无法继续下去。

    所以我们考虑怎样不需要维护也能得到答案,那么考虑到逆推,同时把这个c数组(牌堆)更好的运用上。

    我们考虑还剩下i个人,从庄数其第j个人获胜的概率是多少。

    那么我们可以发现这样做可以保证,每一个状态都能根据c从一个确定的地方转移过来。

    仔细来讲:

    我们可以首先枚举庄家抽到的卡牌k,得到这一轮被淘汰的人的位置c

    如果c=j ,就不要考虑了(因为这表示此轮第j个人被淘汰)。

    而第c个人被淘汰之后,剩下的i-1个人要组成一个新的环,庄家为第c个人的下一个。

    c>j时,第j个人是新的环里从新庄家数起的第ic+j个人,

    c<j时,第j个人是新的环里从新庄家数起的第jc个人。

    这样就基本完成了这个题目。

    听某些巨lao讲一般的概率DP都是逆推,反正我是先这么受教了,有大佬愿意提出自己的看法,欢迎评论,谢谢

    #include <cstdio>
    using namespace std;
    
    #define RG register
    
    int n,m,c[66];
    double f[66][66];
    
    int main()
    {
        RG int i,j,k,Ne;
        scanf ("%d%d", &n, &m);
        for (i=1;i<=m;++i) scanf ("%d", &c[i]);
        f[1][1]=1.0;
        for (i=2;i<=n;++i)
            for (j=1;j<=i;++j)
                for (k=1;k<=m;++k) {
                    Ne=c[k]%i;
                    if (!Ne) Ne=i;
                    if (Ne<j) f[i][j]+=f[i-1][j-Ne]/m;
                    if (Ne>j) f[i][j]+=f[i-1][i-Ne+j]/m;
                }
        for (i=1;i<=n;++i) printf ("%.2lf%% ", f[n][i]*100.0);
        return 0;
    }
  • 相关阅读:
    Docker笔记
    使用NextCloud搭建私有云盘
    docker轻量级管理工具
    docker仓库使用+harbor私有仓库部署
    防DDOS攻击解决方案
    MongoDB非关系型数据库
    监控磁盘使用率解决方案
    部署SonarQube代码质量检查7.7版本
    Jenkins的权限控制
    Jenkins分布式构建
  • 原文地址:https://www.cnblogs.com/Bhllx/p/9839396.html
Copyright © 2020-2023  润新知