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;
}

 

posted @ 2013-04-25 22:59  Titanium  阅读(390)  评论(0编辑  收藏  举报