【期望DP】BZOJ2318-[Spoj4060]Game with probability Problem

【题目大意】

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

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

【思路】

不会23333详细题解看这里:

详细的一些细节我放在注释里面了w

 1 #include<iostream> 
 2 #include<cstdio>
 3 #include<cstring>
 4 #include<iostream>
 5 #include<algorithm>
 6 using namespace std;
 7 const int MAXN=1000+5;
 8 double f[MAXN],g[MAXN],p,q;
 9 
10 void solve()
11 {
12     int n;
13     scanf("%d",&n);
14     n=min(n,1000);
15     //由于n很大的时候,概率几乎不再发生改变,则只需要取和1000中较小的即可 
16     scanf("%lf%lf",&p,&q); 
17     f[0]=0,g[0]=1;
18     for(int i=1;i<=n;i++)
19     {
20         if(f[i-1]>g[i-1])p=1-p,q=1-q;
21         //这里p和q表示的含义与题意不同,含义为当前投掷出正面朝上情况的概率
22         //如果还剩i-1个石头时,A先手更有利,则在还是i个石头的时候,A希望B拿掉当前石头,B也希望A拿掉,故均希望反面向上。
23         //这种情况下,正面朝上的概率就是1-p/1-q 
24         //如果还剩i-1个石头时,A后手更有利,则两个人都希望自己能选,正面朝上的概率就是p/q 
25         f[i]=(p*g[i-1]+(1-p)*q*f[i-1])/(1-(1-p)*(1-q));
26         g[i]=(q*f[i-1]+(1-q)*p*g[i-1])/(1-(1-p)*(1-q));
27         if(f[i-1]>g[i-1])p=1-p,q=1-q;
28     }
29     printf("%.6lf
",f[n]);
30 }
31 
32 int main()
33 {
34     int T;
35     scanf("%d",&T);
36     while (T--) solve();
37     return 0;
38 }
原文地址:https://www.cnblogs.com/iiyiyi/p/5779710.html