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 eq 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
",ans);
}

int main()
{
    t=read();
    while (t--)
    {
        init();
        work();
        out();
    }
    return 0;
}
原文地址:https://www.cnblogs.com/encodetalker/p/10808033.html