bzoj 4008 [HNOI2015] 亚瑟王

bzoj 4008 [HNOI2015] 亚瑟王

题面

[题面][https://www.lydsy.com/JudgeOnline/problem.php?id=4008]

题解

我们令\(f[i][j]\)表示当前考虑了前\(i\)张卡牌,前\(i\)张牌一共剩下\(j\)次机会的概率是多少

那么\(f[0][r]=1\)

然后递推地求解

如果第\(i+1\)张卡牌没有用到 那么\(f[i+1][j]+=f[i][j]\times (1-p[i+1])^j\)

如果第\(i+1\)张卡牌被用到了,那么少了一次机会,多了一些伤害

\(f[i+1][j-1]+=f[i][j]\times (1-(1-p[i+1])^j)\)

然后答案会加\(f[i][j]\times(1-(1-p[i+1])^j)\times d[i+1]\)

就是概率乘伤害

Review

这题据TRCYX说是NewTrain最难得期望dp

我觉得主要是状态难想,因为考虑到某一张牌只和前面的牌有关,和后面的牌无关,而且出牌的顺序也不影响答案,于是把\(r\)轮搞成\(r\)次机会,所以想到这个状态

Code

#include<stdio.h>
#include<cstring>
#include<cstdlib>
#include<algorithm>
#include<vector>
#include<map>
#include<set>
#include<cmath>
#include<iostream>
#include<queue>
#include<string>
using namespace std;
typedef long long ll;
typedef pair<int,int> pii;
typedef long double ld;
typedef unsigned long long ull;
typedef pair<long long,long long> pll;
#define fi first
#define se second
#define pb push_back
#define mp make_pair
#define rep(i,j,k)  for(register int i=(int)(j);i<=(int)(k);i++)
#define rrep(i,j,k) for(register int i=(int)(j);i>=(int)(k);i--)

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

int T;
int n,r,d[255];
double p[255];
double f[255][255],pw[255][255];

int main()
{
    T=read();
    while(T--)
    {
        n=read();r=read();
        memset(f,0,sizeof(f));
        for(int i=1;i<=n;i++)
        {
            scanf("%lf",&p[i]);
            d[i]=read();
        }
        double ans=0;
        for(int i=1;i<=n;i++)
        {
            pw[i][0]=1;
            for(int j=1;j<=r;j++)pw[i][j]=pw[i][j-1]*(1-p[i]);
        }
        f[0][r]=1;
        for(int i=0;i<n;i++)
            for(int j=0;j<=r;j++)
            {
                f[i+1][j]+=f[i][j]*pw[i+1][j];
                if(j-1>=0)
                {
                    f[i+1][j-1]+=f[i][j]*(1-pw[i+1][j]);
                    ans+=f[i][j]*(1-pw[i+1][j])*d[i+1];
                }
            }
        printf("%.10lf\n",ans);
    }
    return 0;
}

猜你喜欢

转载自www.cnblogs.com/wawawa8/p/9557552.html