• 「HNOI2015」亚瑟王


    传送门

    Description

    小 K 不慎被 LL 邪教洗脑了,洗脑程度深到他甚至想要从亚瑟王邪教中脱坑。

    他决定,在脱坑之前,最后再来打一盘亚瑟王。既然是最后一战,就一定要打得漂亮。众所周知,亚瑟王是一个看脸的游戏,技能的发动都是看概率的。作为一个非洲人,同时作为一个前 OIer,小 K 自然是希望最大化造成伤害的期望值。但他已经多年没写过代码,连 Spaly 都敲不对了,因此,希望你能帮帮小 K,让他感受一下当欧洲人是怎样的体验。

    本题中我们将考虑游戏的一个简化版模型。

    玩家有一套卡牌,共 (n) 张。游戏时,玩家将 (n) 张卡牌排列成某种顺序,排列后将卡牌按从前往后依次编号为 (1 sim n)。本题中,顺序已经确定,即为输入的顺序。

    每张卡牌都有一个技能。第 (i) 张卡牌的技能发动概率为 (p_i),如果成功发动,则会对敌方造成 (d_i) 点伤害。也只有通过发动技能,卡牌才能对敌方造成伤害。基于现实因素以及小 K 非洲血统的考虑,(p_i) 不会为 0,也不会为 1,即 (0 < p_i < 1)

    一局游戏一共有 (r) 轮。在每一轮中,系统将从第一张卡牌开始,按照顺序依次考虑每张卡牌。在一轮中,对于依次考虑的每一张卡牌:

    1. 如果这张卡牌在这一局游戏中已经发动过技能,则
      1.1 如果这张卡牌不是最后一张,则跳过之(考虑下一张卡牌); 否则(是最后一张),结束这一轮游戏。
    2. 否则(这张卡牌在这一局游戏中没有发动过技能),设这张卡牌为第 (i) 张。
      2.1 将其以 (p_i) 的概率发动技能。
      2.2 如果技能发动,则对敌方造成 (d_i)点伤害,并结束这一轮。
      2.3 如果这张卡牌已经是最后一张(即 (i) 等于 (n)),则结束这一轮;否则,考虑下一张卡牌。

    请帮助小 K 求出这一套卡牌在一局游戏中能造成的伤害的期望值。

    Solution

    本题想到对于每个卡牌单独求概率并不难

    难点在于每轮在取到卡牌后就会停止,所以如果是对游戏过程进行(dp)会非常麻烦

    因为你可能需要考虑当前以获得卡牌的集合

    题解的做法巧妙地排除了这方面的难题,转而对序列本身进行(dp)

    因为轮数是已知的,并且数列的顺序也是已知的

    未知的是每一轮的停止位置,所以本题的(dp)实质上是在对每一轮的结束位置进行(dp)

    (dp[i][j])表示全局结束后,前(i)个中选了(j)个的概率,(f[i])表示第(i)个被选上的概率,(p[i])表示输入的那个概率。考虑是否选择第(i)个数进行转移,并把选择第(i)个数的贡献计入(f[i])


    Code 

    #include<bits/stdc++.h>
    #define ll long long
    #define dbg1(x) cerr<<#x<<"="<<(x)<<" "
    #define dbg2(x) cerr<<#x<<"="<<(x)<<"
    "
    #define dbg3(x) cerr<<#x<<"
    "
    using namespace std;
    #define reg register
    #define db double
    inline 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<<3)+(x<<1)+ch-'0';ch=getchar();}
    	return x*f;
    }
    const int MN=225,MR=137;
    int n,r,d[MN];
    db p[MN],pw[MN][MN],f[MN][MN],P[MN],ans;
    int main()
    {
    	int Cas=read();
    	reg int i,j;
    	while(Cas--)
    	{
    		n=read();r=read();
    		for(i=1;i<=n;++i)scanf("%lf",&p[i]),d[i]=read();
    		memset(f,0,sizeof f);
    		memset(P,0,sizeof P);
    		reg int i,j;
            for(i=1;i<=n;++i)for(pw[i][0]=j=1;j<=r;++j)
                pw[i][j]=pw[i][j-1]*(1.-p[i]);
            f[1][0]=pw[1][r];f[1][1]=P[1]=1.-f[1][0];
            for(i=2;i<=n;++i)for(j=0;j<=r&&j<=i;++j)
    		{
                f[i][j]+=f[i-1][j]*pw[i][r-j];
                if(j) f[i][j]+=f[i-1][j-1]*(1-pw[i][r-j+1]),
                    P[i]+=f[i-1][j-1]*(1-pw[i][r-j+1]);
            }
            ans=0.;
            for(i=1;i<=n;++i)ans+=P[i]*(db)d[i];
            printf("%.10lf
    ",ans);
    	}
    	return 0;
    }
    


    Blog来自PaperCloud,未经允许,请勿转载,TKS!

  • 相关阅读:
    JSP中9大内置对象类型
    使用JSP/Servalet技术开发新闻发布系统------JSP数据交互一
    BZOJ5306: [Haoi2018]染色
    BZOJ4695: 最假女选手
    BZOJ4355: Play with sequence
    BZOJ3771: Triple
    BZOJ4057: [Cerc2012]Kingdoms
    BZOJ3302: [Shoi2005]树的双中心
    BZOJ4036: [HAOI2015]按位或
    12.24 ~ 12.30周训练计划+总结
  • 原文地址:https://www.cnblogs.com/PaperCloud/p/11625516.html
Copyright © 2020-2023  润新知