bzoj4008 [HNOI2015]亚瑟王

题目链接:bzoj4008

对于答案的计算有一个很显然的思路,记第\(i\)张卡牌在游戏中被发动的概率为\(f_i\),则\(Ans=\sum_{i=1}^nf_id_i\)

考虑如何计算\(f_i\),可以用\(1-\)不发动这张卡牌的概率

不发动这张卡牌的概率\(=(1-p_i)^{它被考虑的轮数}*1^{它不被考虑的轮数}*该局面出现的概率\)

对于最后一项可以考虑dp,记\(dp_{i,j}\)表示前\(i\)张卡牌中发动\(j\)张的概率,按照当前是否发动第\(i\)张进行转移

1)发动第\(i\)张,那么首先\(j>0\),其次在\(j-1\)轮中,由于发动了\(i\)之前的卡牌故不会考虑\(i\),所以这种情况对\(dp_{i,j}\)的贡献为\(dp_{i-1,j-1}*(1-(1-p_i)^{r-(j-1)})\)

2)不发动第\(i\)张,和第一种同理,对答案贡献为\(dp_{i-1,j}(1-p_i)^{r-j}\),注意此时\(i\neq j\)

综合起来就是
\[ dp_{i,j}=dp_{i-1,j-1}*(1-(1-p_i))^{r-(j-1)}+dp_{i-1,j}*(1-p_i)^{r-j} \]
好了现在\(f_i\)的计算就比较轻松了,枚举在\(i\)之前选了\(j\)张卡牌,那么在这\(j\)轮是不会考虑\(i\)这一张卡牌的,故
\[ f_i=\sum_{j=0}^{min(i-1,r)}dp_{i-1,j}(1-(1-p_i)^{r-j}) \]

预处理\((1-p_i)^j\)以加速运算

#include<iostream>
#include<string.h>
#include<string>
#include<stdio.h>
#include<algorithm>
#include<vector>
#include<queue>
#include<map>
using namespace std;
int n,m,r,d[1010],t;
double p[1010],powe[1010][1010],dp[1010][1010],f[1010];

int read()
{
    int x=0,f=1;char ch=getchar();
    while ((ch<'0') || (ch>'9')) {if (ch=='-') f=-1;ch=getchar();}
    while ((ch>='0') && (ch<='9')) {x=x*10+(ch-'0');ch=getchar();}
    return x*f;
}

void init()
{
    n=read();r=read();
    memset(f,0.0,sizeof(f));
    memset(dp,0.0,sizeof(dp));
    int i,j;
    for (i=1;i<=n;i++) scanf("%lf%d",&p[i],&d[i]);
    for (i=1;i<=n;i++)
    {
        powe[i][0]=1.0;
        for (j=1;j<=r;j++) powe[i][j]=powe[i][j-1]*(1-p[i]);
    }
}

void work()
{
    int i,j;
    dp[1][1]=1.0-powe[1][r];dp[1][0]=powe[1][r];
    for (i=2;i<=n;i++)
    {
        for (j=0;j<=min(i,r);j++)
        {
            if (j) dp[i][j]+=dp[i-1][j-1]*(1.0-powe[i][r-j+1]); 
            if (i!=j) dp[i][j]+=dp[i-1][j]*powe[i][r-j];
        }
    }
}

void out()
{
    double ans=0.0;f[1]=1-powe[1][r];
    int i,j;
    for (i=2;i<=n;i++) 
    {
        for (j=0;j<=min(i-1,r);j++)
            f[i]+=dp[i-1][j]*(1.0-powe[i][r-j]);
    }
    for (i=1;i<=n;i++) ans+=f[i]*d[i];
    printf("%0.10lf\n",ans);
}

int main()
{
    t=read();
    while (t--)
    {
        init();
        work();
        out();
    }
    return 0;
}

猜你喜欢

转载自www.cnblogs.com/encodetalker/p/10808033.html