zoukankan      html  css  js  c++  java
  • BZOJ 2318: Spoj4060 game with probability Problem (概率dp)(博弈论)

    2318: Spoj4060 game with probability Problem

    Description

    AliceBob在玩一个游戏。有n个石子在这里,AliceBob轮流投掷硬币,如果正面朝上,则从n个石子中取出一个石子,否则不做任何事。取到最后一颗石子的人胜利。Alice在投掷硬币时有p的概率投掷出他想投的一面,同样,Bobq的概率投掷出他相投的一面。

    现在Alice先手投掷硬币,假设他们都想赢得游戏,问你Alice胜利的概率为多少。

    Input

    第一行一个正整数t,表示数据组数。

    对于每组数据,一行三个数npq

    Output

    对于每组数据输出一行一个实数,表示Alice胜利的概率,保留6位小数。

    Sample Input

    1

    1 0.5 0.5

    Sample Output

    0.666667

    HINT

    数据范围:

    1<=t<=50

    0.5<=p,q<=0.99999999

    对于100%的数据 1<=n<=99999999


    传送门

    概率dp的部分不难写,博弈论的策略没想出来。

    设$f[i]$表示有$i$枚石子,先手获胜的概率;

       $g[i]$表示有$i$枚石子,后手获胜的概率;

    则当有$i+1$枚石子时:

      若$f[i]>g[i]$,则$Alice$希望在有$i$枚石子时取得先手,那么她希望这轮不取;

      否则,$Alice$希望这轮取得石子;

    当Alice希望取得石子时:

      若Alice在本轮中先手,则有$p$的概率在下轮取得后手,有$1-p$的概率在本轮取得后手;

      若Alice在本轮中后手,则有$q$的概率在下轮取得先手,有$1-q$的概率在本轮取得先手;

    即$$egin{cases}f_i=p*g_{i-1}+(1-p)*g_i\g_i=q*f_{i-1}+(1-q)*f_iend{cases}$$

    化简得$$f_i=frac{p*g_{i-1}+(1-p)*q*f_{i-1}}{1-(1-p)*(1-q)}$$

    $$g_i=frac{q*f_{i-1}+(1-q)*p*g_{i-1}}{1-(1-p)*(1-q)}$$


    当Alice不希望取得石子时:$p$和$(1-p)$ $q$和$(1-q)$取反即可

     

    倒推dp即可。

    有两个注意的点:

      n很大,数组肯定是装不下的,显然要用滚动数组。

      O(n)的时间复杂度显然是跑不过的,打表可以发现答案是收敛的,n很大的时候前6位小数已经固定了,n取min(n,100)就好。似乎是个常见的套路,还是too young,见得不够多。

     1 #include<cstdio>
     2 #include<algorithm>
     3 #define foru(i,x,y) for(int i=x;i<=y;i++)
     4 using namespace std;
     5 int T,n,fl;
     6 double f[2],g[2],p,q,p_,q_;
     7 int main(){
     8     scanf("%d",&T);
     9     while(T--){
    10         scanf("%d%lf%lf",&n,&p,&q);
    11         n=min(n,100);
    12         f[0]=0;g[0]=1;q_=1-q;p_=1-p;
    13         int i=1;
    14         foru(j,1,n){
    15             if(f[i^1]>g[i^1])swap(p_,p),swap(q_,q),fl=1;
    16                 f[i]=(p*g[i^1]+p_*q*f[i^1])/(1-q_*p_);
    17                 g[i]=(q*f[i^1]+q_*p*g[i^1])/(1-q_*p_);
    18             if(fl==1)swap(p_,p),swap(q_,q),fl=0;i^=1;
    19         }
    20         printf("%.6lf
    ",f[i^1]);
    21     }
    22 }
  • 相关阅读:
    java基础--字符转换Unicode
    java基础---集合框架
    洛谷 P2049 魔术棋子(vector)
    洛谷 P3133 [USACO16JAN]Radio Contact G
    洛谷 P2679 子串
    洛谷 P2549 计算器写作文
    洛谷 P2758 编辑距离
    洛谷 P1481 魔族密码
    洛谷 P1754 球迷购票问题
    洛谷 P2782 友好城市
  • 原文地址:https://www.cnblogs.com/y-m-y/p/7017268.html
Copyright © 2011-2022 走看看