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

    Description:

    你有(n)张牌,每轮需要依次打出这些牌,每张牌有(p_i)的概率打出,造成(d_i)的伤害,且打出后直接跳至下轮,这张牌不得再使用,否则继续考虑下一张牌,问最终伤害的期望

    Hint:

    (n,r le 200​)

    Solution:

    好难的期望题,主要瓶颈在于如何处理跳至下一轮

    首先由期望的线性性,我们可以算出每张牌打出的概率,最后再乘上它的(d_i)加起来

    (这样处理会比较方便,可以直接对概率dp)

    考虑设状态 (f[i][j]) 表示在所有(r)中,(i)张牌打出(j)张的概率

    于是有 :

    [q[i]=sumlimits_{j=0}^{r}f[i-1][j]cdot(1-(1-p[i])^{r-j}) ]

    ((q[i])为打出概率)

    考虑怎么算(f),我们分两种情况讨论,出或不出:

    [f[i][j]+=f[i-1][j]cdot(1-p[i])^{r-j} ]

    [f[i][j]+=f[i-1][j-1]cdot(1-(1-p[i])^{r-j+1}) ]

    其实这个(f)设的实在很巧妙,它隐性的包含了卡牌被考虑的次数

    并且如果不设前i张的话,会涉及到之前一张牌是否被选的信息,不好转移

    所以它没有考虑第几轮(因为轮的顺序与卡牌被考虑的次数无关),而是站在全局角度

    从最简单的第一张牌的状态开始推

    #include <map>
    #include <set>
    #include <stack>
    #include <cmath>
    #include <queue>
    #include <cstdio>
    #include <cstring>
    #include <cstdlib>
    #include <iostream>
    #include <algorithm>
    #define ls p<<1 
    #define rs p<<1|1
    using namespace std;
    typedef long long ll;
    const int mxn=1e3+5;
    int n,m,r,T,cnt,d[mxn],hd[mxn];
    double p[mxn],q[mxn],f[mxn][mxn],pw[mxn][mxn];
    
    inline int read() {
    	char c=getchar(); int x=0,f=1;
    	while(c>'9'||c<'0') {if(c=='-') f=-1;c=getchar();}
    	while(c<='9'&&c>='0') {x=(x<<3)+(x<<1)+(c&15);c=getchar();}
    	return x*f;
    }
    inline void chkmax(int &x,int y) {if(x<y) x=y;}
    inline void chkmin(int &x,int y) {if(x>y) x=y;}
    
    struct ed {
    	int to,nxt;
    }t[mxn<<1];
    
    inline void add(int u,int v) {
    	t[++cnt]=(ed) {v,hd[u]}; hd[u]=cnt;
    }
    
    void init() {
    	memset(f,0,sizeof(f)); memset(q,0,sizeof(q));
    	for(int i=0;i<n;++i) {
    		pw[i][0]=1.0;
    		for(int j=1;j<=r;++j) 
    			pw[i][j]=pw[i][j-1]*(1.0-p[i]);
    	}
    }
    
    double solve() {
    	f[0][0]=pw[0][r]; f[0][1]=q[0]=1.0-f[0][0]; 
    	for(int i=1;i<n;++i) {
    		for(int j=0;j<=r;++j) {
    			q[i]+=f[i-1][j]*(1.0-pw[i][r-j]); 
    			//状态 sigma_j f[i][j] 不重不漏的枚举了所有状态,且方便算答案,比较巧妙
    			f[i][j]+=f[i-1][j]*pw[i][r-j];
    			if(j) f[i][j]+=f[i-1][j-1]*(1.0-pw[i][r-j+1]);
    		}
    	}
    	double res=0.0;
    	for(int i=0;i<n;++i) res+=1.0*d[i]*q[i];
    	return res;
    }
    
    int main()
    {
    	T=read();
    	while(T--) {
    		n=read(); r=read();
    		for(int i=0;i<n;++i) scanf("%lf%d",p+i,d+i);
    		init(); printf("%.10lf
    ",solve());
    	}
        return 0;
    }
    
    
  • 相关阅读:
    Dependent Parameters in Concurrent Program using Special Value Set
    USER Management | Role Categories | Roles | Indirect Responsibilities
    asp.net core 1.0初识
    ASP.NET Core管道深度剖析
    linux图机界面机制
    类对象管理方式
    UNICODE串转换成char类型串的四种方法
    进程句柄表与创建句柄表
    虚拟化技术
    Windows基于Apache的svn服务器配置
  • 原文地址:https://www.cnblogs.com/list1/p/10587110.html
Copyright © 2011-2022 走看看