• TopCoder


    TopCoder - 12349 SRM579 Round1 Div1 RockPaperScissors (概率dp)

    题目大意:

    (n)个骰子,每个骰子有300个面,其中有(a_i,b_i,c_i)分别为石头/布/剪刀

    每轮你选择出石头/剪刀/布,然后会从剩下的骰子中随机取一个再随机结果,但是你不知道取的是什么骰子

    赢一局的权值为3,平局为1

    求最优情况下最大的权值期望

    [ ]

    题目分析:

    显然当前的局面只和已经抽出的石头/布/剪刀的数量有关(因为这是你唯一的决策依据,也是唯一影响局面的)

    乍一看非常抽象的决策过程,实在无法通过分析得到每一种局面下应该作出的决策

    于是考虑能否直接把每一种局面出现的概率求出,决策后将期望线性相加

    不妨把随机取出的骰子放在一个序列上,一个局面是由已经出现的骰子和当前第(i)次决策的骰子组成的

    (dp_{i,j,k,typ})表示已经出现的骰子中出现(i,j,k)个石头/布/剪刀,当前决策时骰子结果为(typ)的概率

    实际在(dp)时,(typ)一维需要额外加入一个值表示未确定下一个是什么

    考虑对于每个骰子,枚举它是已经出现/正在决策/在第(i)次决策之后出现,将其概率累和

    (dp)状态为(O(n^3)),转移次数为(O(n)),复杂度为(O(n^4))

    最后对于每种局面计算最优的决策即可

    #include<bits/stdc++.h>
    using namespace std;
    
    #define rep(i,a,b) for(int i=a,i##end=b;i<=i##end;++i)
    #define drep(i,a,b) for(int i=a,i##end=b;i>=i##end;--i)
    template <class T> inline void cmin(T &a,T b){ ((a>b)&&(a=b)); }
    template <class T> inline void cmax(T &a,T b){ ((a<b)&&(a=b)); }
    
    class RockPaperScissors {
    private:
    	static const int N=53;
    	static const int eps=1e-9;
    	double F[N][N][N][4],G[N][N][N][4],w[3];
    	double C[N][N];
    
    public:
    	
    	double bestScore(vector <int> w1, vector <int> w2, vector <int> w3) {
    		int n=w1.size();
    		rep(i,0,n) rep(j,C[i][0]=1,i) C[i][j]=C[i-1][j-1]+C[i-1][j];
    		memset(F,0,sizeof F),F[0][0][0][3]=1;
    		rep(i,1,n) {
    			w[0]=w1[i-1]/300.0; w[1]=w2[i-1]/300.0; w[2]=w3[i-1]/300.0;
    			rep(a,0,i) rep(b,0,i-a) rep(c,0,i-a-b) rep(d,0,3) G[a][b][c][d]=F[a][b][c][d];
    			rep(a,0,i) rep(b,0,i-a) rep(c,0,i-a-b) rep(d,0,3) if(G[a][b][c][d]>eps) {
    				// 枚举这个骰子在之前出现过了
    				F[a+1][b][c][d]+=G[a][b][c][d]*w[0];
    				F[a][b+1][c][d]+=G[a][b][c][d]*w[1];
    				F[a][b][c+1][d]+=G[a][b][c][d]*w[2];
    				// 枚举这个骰子为下一个出现的
    				if(d==3) rep(e,0,2) F[a][b][c][e]+=G[a][b][c][d]*w[e];
    			}
    		}
    		double ans=0;
    		rep(a,0,n-1) rep(b,0,n-1-a) rep(c,0,n-1-a-b) {
    			// 决策这一轮出什么
    			double ma=0;
    			rep(d,0,2) cmax(ma,F[a][b][c][d]+F[a][b][c][(d+2)%3]*3);
    			ans+=ma/C[n][a+b+c]/(n-a-b-c);
    		}
    		return ans;
    	}
    };
    
  • 相关阅读:
    C语言中结构体变量之间赋值
    ZOJ
    【微服务干货系列】使用微服务架构之前,你必须知道的
    使用heartbeat+monit实现主备双热备份系统
    rsync 3.1.1源代码编译安装配置
    oracle 11g GRID 中 关于 OLR 须要知道的一些内容
    字母游戏
    移动开发人员应避免的 4 大陷阱
    看看这个经常被0基础程序猿弄不懂的 “事件”
    【剑指offer】和为定值的连续正数序列
  • 原文地址:https://www.cnblogs.com/chasedeath/p/14056819.html
Copyright © 2020-2023  润新知