zoukankan      html  css  js  c++  java
  • BZOJ 4008: [HNOI2015]亚瑟王

    略显麻烦并且套路的概率DP题,被一个初始化坑了好久

    首先根据期望的线性性我们可以求出每张卡使用的概率然后计算答案

    我们先不谈这个概率怎么求,先来想一个一眼能设出来的DP,令(f_{i,j})表示前(i)张牌里选(j)张的概率

    考虑它怎么转移,显然是从(f_{i-1,j})(f_{i-1,j-1})转移过来,然后我们发现按这个顺序DP有一个好处就是一张牌前面有多少张牌被发动了是确定的

    那么这张牌被考虑的次数显然也可以统计出来了,容易得到此时的转移方程

    [f_{i,j}=f_{i,j}+f_{i-1,j} imes (1-p_i)^{r-j} ]

    [f_{i,j}=f_{i,j}+f_{i-1,j-1} imes [1-(1-p_i)^{r-j+1}] ]

    那么我们求出了看似没用的(f_{i,j})能干嘛呢,考虑我们推导(f_{i,j})的时候根据一张牌前面有多少张发动了技能就可以推出这张牌被考虑的次数,那么我们同理可以推导出答案:

    [P(i)=sum_{j=0}^r f_{i-1,j} imes [1-(1-p_i)^{r-j}] ]

    注意关键的边界:第一张牌!稍加分析我们有:

    [f_{1,0}=(1-p_i)^r;P(1)=f_{1,1}=1-(1-p_i)^r ]

    那么这道题就算是做完了,复杂度(O(t imes n imes r))

    #include<cstdio>
    #define RI register int
    #define CI const int&
    using namespace std;
    const int N=225,M=135;
    int t,n,m,d[N]; double ans,tp,p[N][M],f[N][N];
    int main()
    {
        for (scanf("%d",&t);t;--t)
        {
            RI i,j; for (scanf("%d%d",&n,&m),i=1;i<=n;++i)
            scanf("%lf%d",&tp,&d[i]),p[i][0]=1,p[i][1]=1.0-tp;
            for (i=1;i<=n;++i) for (j=2;j<=m;++j) p[i][j]=p[i][j-1]*p[i][1];
            for (f[1][0]=p[1][m],f[1][1]=1.0-p[1][m],i=2;i<=n;++i) for (j=0;j<=m;++j)
            f[i][j]=f[i-1][j]*p[i][m-j]+(j?f[i-1][j-1]*(1.0-p[i][m-j+1]):0);
            for (ans=(1.0-p[1][m])*d[1],i=2;i<=n;++i)
            {
                for (tp=j=0;j<=m;++j) tp+=f[i-1][j]*(1.0-p[i][m-j]);
                ans+=1.0*tp*d[i];
            }
            printf("%.10lf
    ",ans);
        }
        return 0;
    }
    
  • 相关阅读:
    POJ 1611 The Suspects
    POJ 2001 Shortest Prefixes(字典树)
    HDU 1251 统计难题(字典树 裸题 链表做法)
    G++ C++之区别
    PAT 乙级 1013. 数素数 (20)
    PAT 乙级 1012. 数字分类 (20)
    PAT 乙级 1009. 说反话 (20)
    PAT 乙级 1008. 数组元素循环右移问题 (20)
    HDU 6063 17多校3 RXD and math(暴力打表题)
    HDU 6066 17多校3 RXD's date(超水题)
  • 原文地址:https://www.cnblogs.com/cjjsb/p/12241635.html
Copyright © 2011-2022 走看看