【期望DP】BZOJ2318-[Spoj4060]Game with probability Problem
【题目大意】
Alice和Bob在玩一个游戏。有n个石子在这里,Alice和Bob轮流投掷硬币,如果正面朝上,则从n个石子中取出一个石子,否则不做任何事。取到最后一颗石子的人胜利。Alice在投掷硬币时有p的概率投掷出他想投的一面,同样,Bob有q的概率投掷出他相投的一面。
现在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\n",f[n]); 30 } 31 32 int main() 33 { 34 int T; 35 scanf("%d",&T); 36 while (T--) solve(); 37 return 0; 38 }