zoukankan      html  css  js  c++  java
  • BZOJ 4008 【HNOI2015】 亚瑟王

    题目链接:亚瑟王

      这道题好神啊TAT……果然我的dp还是太弱了……

      一开始想了半天的直接dp求期望,结果最后WA的不知所云……

      最后去翻了题解,然后发现先算概率,再求期望……新姿势(get)。

      我们不妨把(r)轮看做(r)次出牌机会,然后令(f_{i,j})表示考虑完前(i)张牌,还剩(j)次机会的概率。

      然后我们从前往后一张张牌考虑过去。对第$i$张牌,枚举还剩$j$次机会,单独考虑一下:

      若这张牌没有发动,那么概率为$(1-p_i)^jf_{i-1,j}$

      若这张牌发动了,那么就是在还剩(j+1)次机会的时候打出这张牌。由于每张牌最多发动一次,那么概率为$(1-(1-p_i)^j)f_{i-1,j+1}$

      于是我们得到了转移方程:$$f_{i,j}=(1-p_i)^jf_{i-1,j}+(1-(1-p_i)^j)f_{i-1,j+1}$$

      然后预处理出$(1-p_i)^j$,一路推过去即可。

      最后再枚举第$i$张牌在还剩$j$次机会时打出,用概率来算一下期望。当然这一步也可以在$dp$的时候就顺便解决。

      下面贴代码:

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #include<cmath>
    #define File(s) freopen(s".in","r",stdin),freopen(s".out","w",stdout)
    #define N 230
    
    using namespace std;
    typedef double llg;
    
    int T,n,r,a[N];
    llg p[N],f[N][N],mi[N][N],ans;
    
    int main(){
    	File("a");
    	scanf("%d",&T);
    	for(int i=0;i<N;i++) mi[0][i]=mi[i][0]=1;
    	while(T--){
    		scanf("%d %d",&n,&r); ans=0;
    		for(int i=1;i<=n;i++){
    			scanf("%lf %d",&p[i],&a[i]);
    			mi[i][1]=1-p[i];
    			for(int j=2;j<=r+1;j++) mi[i][j]=mi[i][j-1]*(1-p[i]);
    		}
    		for(int i=0;i<=r;i++) f[0][i]=0;
    		for(int i=0;i<=n;i++) f[i][r+1]=0;
    		f[0][r]=1;
    		for(int i=1;i<=n;i++)
    			for(int j=0;j<=r;j++){
    				f[i][j]=f[i-1][j]*mi[i][j];
    				f[i][j]+=f[i-1][j+1]*(1-mi[i][j+1]);
    				ans+=f[i-1][j+1]*(1-mi[i][j+1])*a[i];
    			}
    		printf("%.10lf
    ",ans);
    	}
    	return 0;
    }
    

      

  • 相关阅读:
    Cookie:Session,ServletContext
    thrift安装笔记
    Maven笔记
    JVM 几个重要的参数
    dbvisualizer参数设置
    Linux中如何设置java环境变量
    java.net.NoRouteToHostException: No route to host
    新上海滩感想
    也许你的种子永远不会开花,因为他是一棵参天大树
    男子给妻子做了张桌子,他病逝后家人偶然发现...
  • 原文地址:https://www.cnblogs.com/lcf-2000/p/6258723.html
Copyright © 2011-2022 走看看