UVA11427玩纸牌(全概率+递推)

来源:互联网 发布:mac电脑助手 编辑:程序博客网 时间:2024/05/02 04:54
题意:
      一个人玩纸牌游戏,他每天最多玩n局,枚举获胜的概率是a/b,每天玩牌只要获胜概率达到p,那么他今天就不玩了,明天接着玩,如果有一天他的概率没有达到p,(没有达到p的话他今天一定是玩了n次),那么他以后就在也不玩了,问题是在平均的情况下,他能玩多少个晚上的牌?


思路:
      我们可以先算他只玩一天就失败了的概率,P[i][j]表示玩了i次,赢了j次,当
j/i<=p的时候,根据全概率公式,P[i][j] = P[i-1][j]*(1-p)+P[i-1][j-1]*p前面是输了后面是赢了,端点值是P[0][0] = 1 ,P[0][1] = 0,其他部分全都是0,记得要把其他部分清成0,因为更新是不连续的,这样之后只玩一天的概率等于Q = P[n][0] + P[n][1] +.....
这样答案就是(期望)
玩一天 1 * Q
玩两天 2 * Q(1-Q)
玩三天 3 * Q(1-Q)^2
......
化简后 Ans = 1 / Q;
说下化简的方法吧,有两种
(1)
   a 令s = EX/Q = 1+2(1-Q)+3(1-Q)^2+4(1-Q)^3+...

   b     (1-Q)s = (1-Q)+2(1-Q)^2+3(1-Q)^3+....
a - b得到
EX = Qs = 1+(1-Q)+(1-Q)^2+(1-Q)^3+..=1/Q


(2)
设数学期望为e天,把情况分为两类,第一天晚上出头丧气概率Q期望1,第一天晚上兴高采烈,概率(1-Q)期望e + 1,解得 e = Q * 1 + (1 - Q) * (e + 1) => e = 1/Q;




#include<stdio.h>
#include<string.h>


double P[105][105];


int main ()
{
   int n ,a ,b ,i ,j;
   int t ,cas = 1;
   scanf("%d" ,&t);
   while(t--)
   {
      scanf("%d/%d%d" ,&a ,&b ,&n);
      double p = a * 1.0 / b;
      memset(P ,0 ,sizeof(P));
      P[0][0] = 1 ,P[0][1] = 0;
      for(i = 1 ;i <= n ;i ++)
      for(j = 0 ;j * b <= i * a ;j ++)
      {
         P[i][j] = P[i-1][j] * (1 - p) ;
         if(j >= 1)P[i][j] +=  P[i-1][j-1] * p;
      }
      double Ans = 0;
      for(j = 0 ;j * b <= n * a ;j ++)
      Ans += P[n][j];
      printf("Case #%d: %d\n" ,cas ++ ,(int)(1 / Ans));
   }
   return 0;
}
   



0 0
原创粉丝点击