zoukankan      html  css  js  c++  java
  • P3239 [HNOI2015]亚瑟王

    bzoj4008

    题目描述

    小 K 不慎被 LL 邪教洗脑了,洗脑程度深到他甚至想要从亚瑟王邪教中脱坑。他决定,在脱坑之前,最后再来打一盘亚瑟王。既然是最后一战,就一定要打得漂亮。众所周知,亚瑟王是一个看脸的游戏,技能的发动都是看概率的。

    作为一个非洲人,同时作为一个前 OIer,小 K 自然是希望最大化造成伤害的期望值。但他已经多年没写过代码,连 Spaly都敲不对了,因此,希望你能帮帮小 K,让他感受一下当欧洲人是怎样的体验。

    本题中我们将考虑游戏的一个简化版模型。 玩家有一套卡牌,共\(n\) 张。游戏时,玩家将\(n\) 张卡牌排列成某种顺序,排列后将卡牌按从前往后依次编号为 \(1 - n\)。本题中,顺序已经确定,即为输入的顺序。每张卡牌都有一个技能。第$ i$ 张卡牌的技能发动概率为 \(p_i\) ,如果成功发动,则会对敌方造成 \(d_i\)点伤害。也只有通过发动技能,卡牌才能对敌方造成伤害。基于现实因素以及小 K 非洲血统的考虑,\(p_i\)不会为\(0\),也不会为\(1\),即 \(0 < p_i < 1\)

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

    如果这张卡牌在这一局游戏中已经发动过技能,则

    • 如果这张卡牌不是最后一张,则跳过之(考虑下一张卡牌)
    • 否则(是最后一张),结束这一轮游戏。

    否则(这张卡牌在这一局游戏中没有发动过技能),设这张卡牌为第\(i\)

    • 将其以\(p_i\)的概率发动技能。

    • 如果技能发动,则对敌方造成\(d_i\)点伤害,并结束这一轮。

    • 如果这张卡牌已经是最后一张(即\(i=n\)),则结束这一轮;否则,考虑下一张卡牌。

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


    题解

    将期望转换为概率
    如果第\(i\)张被打出的概率是\(s_i\),那答案显然是\(\sum_{i=1}^n s_i d_i\)

    下面求\(s_i\)
    因为每轮只能有一张牌发动,所以将\(r\)轮视为\(r\)个出牌机会
    一开始居然没看见这点,以为是个水题
    考虑设计状态为\(f_{i,j}\),表示前\(i\)个牌,还剩\(j\)个机会没用的概率
    那如何转移?
    比如现在正在考虑第\(i\)个牌,如果选这一个,很显然机会要减一,可以由:

    \[f_{i-1,j+1}(1-(1-p_i)^{j+1}) \]

    转移而来,其中,\((1-p_i)^{j+1}\)就是剩下\(j+1\)次机会都不用\(i\)的概率,然后再用一减它,就是这\(j+1\)次机会中至少让它发动一次的概率

    如果不选,机会不变,可以由:

    \[f_{i-1,j}(1-p_i)^{j} \]

    转移而来,结合上面的阐述,\((1-p_i)^{j}\)就是\(i\)在剩下\(j\)次机会中都不能被用的概率

    最后考虑如何从\(f\)\(s\)转换

    \[s_i=\sum_{j=1}^r f_{i-1,j+1}(1-(1-p_i)^{j+1}) \]

    也就是已经选好前\(i-1\)个牌,剩余任意(不为0)次机会,再乘上刚才说的\((1-(1-p_i)^{j+1})\)就行了

    最后,多测不清零,40分两行泪
    另外清零的时候要清的比实际范围大一点,因为会访问超出实际范围的下标,看代码就知道了

    #include<cstdio>
    #include<algorithm>
    #include<iostream>
    #include<cmath>
    #include<iomanip>
    #include<cstring>
    #define reg register
    #define EN std::puts("")
    #define LL long long
    inline int read(){
    	int x=0,y=1;
    	char c=std::getchar();
    	while(c<'0'||c>'9'){if(c=='-') y=0;c=std::getchar();}
    	while(c>='0'&&c<='9'){x=x*10+(c^48);c=std::getchar();}
    	return y?x:-x;
    }
    int n,r;
    double f[250][250];//f[i][j]为前i张还剩j次机会的概率 
    double p[250];
    int d[250];
    double power[250][250];
    int main(){int T=read();while(T--){
    	n=read();r=read();
    	for(reg int i=1;i<=n;i++){
    		std::scanf("%lf",p+i);d[i]=read();
    		p[i]=1-p[i];power[i][0]=1;power[i][r+1]=0;
    		for(reg int j=1;j<=r;j++)
    			power[i][j]=power[i][j-1]*p[i];
    	}
    	reg double ans=0;
    	for(reg int i=0;i<=240;i++)for(reg int j=0;j<=240;j++)f[i][j]=0;
    	f[0][r]=1;
    	for(reg int i=1;i<=n;i++){
    		reg double s=0;
    		for(reg int j=r;~j;j--){
    			f[i][j]=f[i-1][j]*power[i][j];
    			f[i][j]+=f[i-1][j+1]*(1-power[i][j+1]);
    			s+=f[i-1][j+1]*(1-power[i][j+1]);
    		}
    		ans+=s*d[i];
    	}
    	std::printf("%.10lf\n",ans);
    }
    	return 0;
    }
    
  • 相关阅读:
    图解MySQL | [原理解析] MySQL使用固定的server_id导致数据丢失【转】
    故障分析 | 记一次 MySQL 主从双写导致的数据丢失问题【转】
    MySQL8.0之XtraBackup【转】
    使用pt-table-checksum校验MySQL主从复制【转】
    MySQL基于 GTID 的多源复制【转】
    pyenv虚拟环境管理python多版本和软件库【转】
    MySQL SQL编写笔记
    linux安装oracle客户端【转】
    spring-cloud-gateway获取post请求body参数以及响应数据
    spring-webflux中Flux<DataBuffer> 转String
  • 原文地址:https://www.cnblogs.com/suxxsfe/p/12523895.html
Copyright © 2011-2022 走看看