BZOJ [HNOI2015]亚瑟王 ——期望DP

发现每张卡牌最后起到作用只和是否打出去了有关。

而且每张牌打出去的概率和之前的牌打出去的情况有关。

所以我们按照牌的顺序进行DP。

然后记录$i$张牌中打出$j$张的概率,然后顺便统计答案。

直接对系数进行DP即可。

复杂度$\Theta(NTR)$

#include <map>
#include <ctime>
#include <cmath>
#include <queue>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
#define F(i,j,k) for (int i=j;i<=k;++i)
#define D(i,j,k) for (int i=j;i>=k;--i)
 
double f[250][250],p[250],d[250],ans;
int t,n,r;
 
double ksm(double a,int b)
{
    double ret=1.0;
    for (;b;a*=a,b>>=1) if (b&1) ret*=a;
    return ret;
}
 
int main()
{
    scanf("%d",&t);
    while (t--)
    {
        scanf("%d%d",&n,&r); ans=0;
        F(i,1,n) scanf("%lf%lf",&p[i],&d[i]);
        F(i,1,n) F(j,1,min(n,r)) f[i][j]=0; f[0][0]=1;
        F(i,1,n)
        {
            f[i][0]=f[i-1][0]*ksm(1-p[i],r);
            F(j,1,min(n,r))
            {
                f[i][j]=f[i-1][j-1]*(1-ksm(1-p[i],r-j+1))
                        +f[i-1][j]*ksm(1-p[i],r-j);
                ans+=f[i-1][j-1]*(1-ksm(1-p[i],r-j+1))*d[i];
            }
        }
//      F(i,1,n)F(j,0,n){printf("%.10f%c",f[i][j],j==n?'\n':' ');}
        printf("%.10f\n",ans);
    }
}

  

posted @ 2017-04-05 17:22  SfailSth  阅读(241)  评论(0编辑  收藏  举报