Topcoder SRM 579 Level Three RockPaperScissors 题解

Topcoder SRM 579 Level Three RockPaperScissors 题解

首先玩家知道的只有\(a,b,c\)。而玩家希望通过\(a,b,c\)推出接下来剪刀石头布的概率。

以剪刀为例,概率为:

\[\mathbb{E}(\mathbb{P(s,a,b,c)}\times \frac{\sum_{i\not \in s}ScissorsProb(i) }{n-a-b-c}\times \frac{1}{n\choose {a+b+c}}|s\in \{1,2...n\},|s|=a+b+c,a+b+c\neq n) \]

也就是每种状态概率的期望,其中\(\mathbb{P(s,a,b,c)}\)\(s\)中有\(a,b,c\)个剪刀石头布的概率。

我们可以把前面的\(P\)看作后面$\sum $的系数。

可以另两个dp:

\(dp_{x,a,b,c}\)表示考虑了前\(x\)个,上述的结果是什么。

\(dp2_{x,a,b,c}\)表示系数总和。

转移也很简单。

code:

const int MAXN=51;
long double dp[2][MAXN][MAXN][MAXN][3],dp2[2][MAXN][MAXN][MAXN][3];
long double p[MAXN][3];
long double C(int A,int B){
	long double ans=1;
	rb(i,B+1,A){
		ans*=i;
		ans/=(i-B);
	}
	return ans;
}
class RockPaperScissors{
	public:
		double bestScore(vector<int> rockProb, vector<int> paperProb, vector<int> scissorsProb){
			int n=rockProb.size();
			rb(i,1,n) p[i][0]=rockProb[i-1]/300.0,p[i][1]=paperProb[i-1]/300.0,p[i][2]=scissorsProb[i-1]/300.0;
			fill((long double*)dp,(long double*)dp+2*MAXN*MAXN*MAXN*3,0);
			fill((long double*)dp2,(long double*)dp2+2*MAXN*MAXN*MAXN*3,0);
			rep(i,3) dp[0][0][0][0][i]=0,dp2[0][0][0][0][i]=1;
			rb(i,1,n){
				fill((long double*)dp[i&1],(long double*)dp[i&1]+MAXN*MAXN*MAXN*3,0);
				fill((long double*)dp2[i&1],(long double*)dp2[i&1]+MAXN*MAXN*MAXN*3,0);
				rb(j,0,n) rb(k,0,n) rb(z,0,n) rep(l,3) if(dp2[(i&1)^1][j][k][z][l]!=0){
					long double val=dp[(i&1)^1][j][k][z][l],val2=dp2[(i&1)^1][j][k][z][l];
					dp[i&1][j+1][k][z][l]+=val*p[i][0];
					dp2[i&1][j+1][k][z][l]+=val2*p[i][0];
					dp[i&1][j][k+1][z][l]+=val*p[i][1];
					dp2[i&1][j][k+1][z][l]+=val2*p[i][1];
					dp[i&1][j][k][z+1][l]+=val*p[i][2];
					dp2[i&1][j][k][z+1][l]+=val2*p[i][2];
					dp[i&1][j][k][z][l]+=val+val2*p[i][l];
					dp2[i&1][j][k][z][l]+=val2;
				}
			}
			long double ans=0;
			rb(j,0,n) rb(k,0,n) rb(z,0,n) {
				if(dp2[n&1][j][k][z][0]==0) continue;
				long double a,b,c;
				a=dp[n&1][j][k][z][0];
				b=dp[n&1][j][k][z][1];
				c=dp[n&1][j][k][z][2];
				int len=j+k+z;
				if(n==len) continue;
				long double comb=C(n,len);
				a/=comb;
				b/=comb;
				c/=comb;
				a/=n-len;
				b/=n-len;
				c/=n-len;
				ans+=max(
				max(
				3.0*a+b
				,
				3.0*b+c
				),
				3.0*c+a
				);
			}
			return ans;
		}
}solver;
posted @ 2021-06-03 22:43  WWW~~~  阅读(118)  评论(0编辑  收藏  举报