原创----杭电1204, 糖果大战解题报告


首先要说明几点:
  1. 这是一道数学题, 对学过随机过程的来说非常easy, 就是一个非常简单的Markov 过程. 不然的话会感觉无从下手, 想彻底搞明白的话,建议看看随机过程的书.
  2. 出题人喜欢玩儿些文字游戏, 设置了一些很无聊的陷阱, 非常无趣.
  3. 代码简单, 但要注意几个条件判断的顺序.
  4. 杭电的bbs上好像有人给出了大概的思路, 不过其中的数学公式有问题.
  我们用X t表示t时刻S君手中的糖果数, 则{X t,t=0, 1, 2.....}是一个Markov Chain. 其状态转移概率为
                    P 00=P NN=1, 这里N = m+n
                    P i, i+1=p(1-q), P i, i-1=(1-p)q, P i, i=1-p(1-q)-q(1-p), i=1, 2, 3...., N-1; (*)
该MC的状态有3类{0}, {1, 2, ..., N-1}, 以及{N}, 其中第二类是非常返的, 第一三类是常返的, 因为每个一非常返态通常仅到达有穷多次, 所以在进行可以在进行有穷多次博弈后, S君或者最终赢得所有糖果, 或者输掉所有糖果.
  这里我们的定义f i=f iN=P(S君经过有限次博弈赢得N个糖果|X 0=i), 这里f i是一个条件概率, 就是开始的时候有i个糖果, 最中赢得N个糖果的概率. 从(*)式可以知道, 当我们有在某时刻t有i个糖果, 我们可以有三种途径可以最终赢得N个糖果. 1. 赢得一个糖果, 概率是p(1-q), 这是下一个时刻t+1G君就有了i+1个糖果. 2. 输掉比赛, 在下一个时刻变成了i-1个糖果, 概率是q(1-p). 3. 打成平手, 下一个时刻还有i个糖果, 概率是1-p(1-q)-q(1-p). 这样我么就可以得到如下公式
                   f i=p(1-q)*f i+1+q(1-p)*f i-1+(1-p(1-q)-q(1-p))*f i
令 P=p(1-q), Q=q(1-p), K=Q/P, 则
                f i+1-f i=K(f i-f i-1)
f i+1-f i是简单的等比数列, 则 f i+1-f i=K i(f 1-f 0). 注意到f N=1,  f 0=0, 这里N=m+n;
       f 2-f 1=Kf 1
       f 3-f 2=K 2f 1
       ................
         f n-f n-1=K n-1f 1
                   ..............
                   f m+n-f m+n-1=K m+n-1f 1
相加一下, f n=(1+K+K 2+...+K n-1)f 1, f n+m=(1+K+K 2+...+K m+n-1)f 1
所以f n=(1+K+K 2+...+K n-1)/(1+K+K 2+...+K m+n-1), k!=1时, 可以化简为f n=(1-K n)/(1-K m+n)
Done!
下面是个AC的代码, enjoy!

 1 #include  < stdio.h >
 2 #include  < math.h >
 3 const   double  EPS  =  1e - 12 ;
 4
 5 ExpandedBlockStart.gifContractedBlock.gifinline  void  solve( int  n,  int  m,  double  p,  double  q)  {
 6ExpandedSubBlockStart.gifContractedSubBlock.gif    if(n==0{
 7        printf("0.00\n");
 8    }

 9ExpandedSubBlockStart.gifContractedSubBlock.gif    else if(m==0{
10        printf("1.00\n");
11    }

12ExpandedSubBlockStart.gifContractedSubBlock.gif    else if(p==0.0||q==1.0{
13        printf("0.00\n");
14    }

15ExpandedSubBlockStart.gifContractedSubBlock.gif    else {
16        double lamda = q*(1-p)/(p*(1-q));
17ExpandedSubBlockStart.gifContractedSubBlock.gif        if(fabs(lamda-1.0)<EPS) {
18            printf("%.2lf\n"double(n)/(m+n));
19        }

20ExpandedSubBlockStart.gifContractedSubBlock.gif        else {
21            double res = (1-pow(lamda, n))/(1-pow(lamda, m+n));
22            printf("%.2lf\n", res);
23        }

24    }

25}

26
27 int  main()
28 ExpandedBlockStart.gifContractedBlock.gif {
29    int n, m;
30    double p, q;
31ExpandedSubBlockStart.gifContractedSubBlock.gif    while(scanf("%d%d%lf%lf"&n, &m, &p, &q)!=EOF) {
32        solve(n, m, p, q);
33    }

34    return 0;
35}

转载于:https://www.cnblogs.com/orangeman/archive/2009/08/03/1537734.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值