ACM-ICPC Live Archive 6204 Poker End Games

概率题

题意:输入case数,每组case两个数字,表示A的点数和B的点数,他们玩游戏,每个人赢的概率都是0.5。输的人要将自己的一部分点数给对方,给的点数是min(na,nb)。例如na=3,nb=2

如果A赢了,B要给2点给A,即全部给完。如果B赢了,A要给2点给B,A变为1,B变为4。一个人的点数为0,那么游戏结束了。题目要你输出两个数学期望,第一个是,这个游戏要结束,要玩多少局的数学期望,另一个是A赢的概率

这题一开始看觉得是期望DP,后来想想也可以不写DP,能把状态表达出来即可。

设一个状态(n,m,c)表示A现在的点数是n,B的点数是m,已经玩了c局。那么游戏结束的状态就是(n,0,c)或者(0,m,c)

而玩了c局,游戏结束,这个概率是多少,就是(0.5)^c , 因为每次玩无论怎样概率都是0.5

而这个游戏是可以无限玩下去的(这个很容易想到,其中sample2就可以无限玩下去),所以算这个数学期望和概率是没有尽头的,但是输出说了,精确到10^-5,当游戏局数很大是,不会再对数学期望和概率产生大的影响,在精度范围内

所以搜索的时候,可以限制深度,即设定一个局数,超过了这个局数就返回不要继续算下去

 

而每到游戏结束的时候,就可以计算数学期望和概率

数学期望 = sum(xi*pi)

概率 = sum(pi)

 

#include <cstdio>

#include <cstring>

#define LIM 40

#define min(a,b) ((a)<(b)?(a):(b))



double EX[2];



double cal(int c)

{

   double ans = 1;

   for(int i=1; i<=c; i++)

      ans *= 0.5;

   return ans;

}



void dfs(int n ,int m , int c)

{

   if(c > LIM) return ;  //限深度搜索

   if( n==0 || m==0) //游戏结束

   {

      double p = cal(c);

      EX[0] += c*p;

      if(m==0) EX[1] += p;

      return ;

   }

   int res = min(n,m);

   dfs(n-res , m+res , c+1);

   dfs(n+res , m-res , c+1);

}



int main()

{

   int T;

   scanf("%d",&T);

   for(int t=1; t<=T; t++)

   {

      int n,m;

      scanf("%d%d",&n,&m);

      EX[0]=EX[1]=0;

      dfs(n,m,0);

      printf("Case %d: %.6lf %.6lf\n",t,EX[0],EX[1]);

   }

   return 0;

}

 

你可能感兴趣的:(games)