• bzoj 4008: [HNOI2015]亚瑟王


    Description
    小 K 不慎被 LL 邪教洗脑了,洗脑程度深到他甚至想要从亚瑟王邪教中脱坑。
    他决定,在脱坑之前,最后再来打一盘亚瑟王。既然是最后一战,就一定要打得漂
    亮。众所周知,亚瑟王是一个看脸的游戏,技能的发动都是看概率的。作为一个非
    洲人,同时作为一个前 OIer,小 K 自然是希望最大化造成伤害的期望值。但他已
    经多年没写过代码,连 Spaly都敲不对了,因此,希望你能帮帮小 K,让他感受一
    下当欧洲人是怎样的体验。
    本题中我们将考虑游戏的一个简化版模型。
    玩家有一套卡牌,共 n张。游戏时,玩家将 n 张卡牌排列成某种顺序,排列后
    将卡牌按从前往后依次编号为 1 ~ n。本题中,顺序已经确定,即为输入的顺序。
    每张卡牌都有一个技能。第 i 张卡牌的技能发动概率为 pi,如果成功发动,则会对
    敌方造成di点伤害。也只有通过发动技能,卡牌才能对敌方造成伤害。基于现实因
    素以及小K非洲血统的考虑,pi不会为 0,也不会为 1,即 0 < pi < 1。
    一局游戏一共有 r 轮。在每一轮中,系统将从第一张卡牌开始,按照顺序依次
    考虑每张卡牌。在一轮中,对于依次考虑的每一张卡牌:
    1如果这张卡牌在这一局游戏中已经发动过技能,则
    1.1 如果这张卡牌不是最后一张,则跳过之(考虑下一张卡牌);
    否则(是最后一张),结束这一轮游戏。
    2否则(这张卡牌在这一局游戏中没有发动过技能),设这张卡牌为第 i 张
    2.1将其以 pi的概率发动技能。
    2.2如果技能发动,则对敌方造成 di点伤害,并结束这一轮。
    2.3如果这张卡牌已经是最后一张(即 i 等于n),则结束这一轮;否则,
    考虑下一张卡牌。
    请帮助小 K 求出这一套卡牌在一局游戏中能造成的伤害的期望值。

    解题报告:
    这题用到了期望的线性性质,即 (E(xy)=E(x)+E(y))
    那么这样就可以转化为求出每一张牌的使用概率,最后乘上该牌的伤害值即可
    考虑如何求使用的概率:
    定义(f[i][j])表示前i张牌,有j张牌用在了i之前,那么对于第i张牌就有打或不打两种转移:
    (f[i][j]=f[i-1][j]*(1-q[i])^{r-j})
    (f[i][j]=f[i-1][j-1]*(1-(1-q[i])^{r-j}))
    因为有j张牌打在i之前,所以与i无关,剩下的r-j张牌如果不打在i上,那么每一回合i就贡献((1-q[i])),所以乘上((1-q[i])^{r-j})
    最后i使用的概率(v[i]=sum_{j=0}^{m}f[i-1][j]*(1-(1-q[i])^{r-j}))
    这样累加可以保证i必然打出

    #include <algorithm>
    #include <iostream>
    #include <cstdlib>
    #include <cstring>
    #include <cstdio>
    #include <cmath>
    #define RG register
    #define il inline
    #define iter iterator
    #define Max(a,b) ((a)>(b)?(a):(b))
    #define Min(a,b) ((a)<(b)?(a):(b))
    using namespace std;
    const int N=225;
    double p[N],f[N][N],t[N][N],v[N];int n,m,d[N];
    void work()
    {
    	memset(f,0,sizeof(f));
    	scanf("%d%d",&n,&m);
    	for(int i=1;i<=n;i++){
    		scanf("%lf%d",&p[i],&d[i]);
    	}
    	for(int j=1;j<=n;j++){
    		t[j][0]=1;
    		for(int i=1;i<=m;i++)t[j][i]=t[j][i-1]*(1-p[j]);
    	}
    	f[1][0]=t[1][m];f[1][1]=1-t[1][m];v[1]=1-t[1][m];
    	for(int i=2;i<=n;i++){
    		v[i]=0;
    		for(int j=0,tmp=Min(m,i);j<=tmp;j++){
    			v[i]+=f[i-1][j]*(1.0-t[i][m-j]);
    			f[i][j]+=f[i-1][j]*t[i][m-j];
    			if(j)f[i][j]+=f[i-1][j-1]*(1.0-t[i][m-j+1]);
    		}
    	}
    	double ans=0;
    	for(int i=1;i<=n;i++){
    		ans+=d[i]*v[i];
    	}
    	printf("%.10lf
    ",ans);
    }
    
    int main()
    {
    	int T;cin>>T;
    	while(T--)work();
    	return 0;
    }
    
    
  • 相关阅读:
    hdu 5101 Select
    hdu 5100 Chessboard
    cf B. I.O.U.
    cf C. Inna and Dima
    cf B. Inna and Nine
    cf C. Counting Kangaroos is Fun
    Radar Installation 贪心
    spfa模板
    Sequence
    棋盘问题
  • 原文地址:https://www.cnblogs.com/Yuzao/p/7497356.html
Copyright © 2020-2023  润新知