CF148D Bag of mice (期望dp)
# 解题思路
~~这怕是本蒟蒻第一个独立做出来的期望$dp$的题,发篇题解庆祝一下~~。首先,应该是能比较自然的想出状态设计$f[i][j][0/1]$ 表示当前还剩 $i$个白老鼠,$j$个黑老鼠,当前是$A/B$抓的概率。有个问题似乎因为当其中一个人抓到白老鼠时游戏就结束了,而在转移过程中比较难表示出来这个,但换状态的话比较难转移。所以要想一个办法,因为如果知道当前有$i$只白老鼠和$j$只黑老鼠的话,那么当前人获胜的概率可以$O(1)$的算出来,$p=\dfrac {i}{i+j}$。所以转移时只去转移那些抓黑老鼠的状态,而答案则在转移中更新就行了,具体转移和实现看代码。
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#include<iostream> #include<cstdio> #include<cstring> #include<algorithm> using namespace std; const int MAXN = 1005; int w,b; double f[MAXN][MAXN][2],ans; int main(){ cin>>w>>b;int n=w+b; f[w][b][0]=1;if((w|b))ans=(double)w/n; //初值是还剩 w个白老鼠,b个黑老鼠,当前A取的概率是1。 for(int i=w;i>=0;i--) for(int j=b-(i==w);j>=0;j--){ f[i][j][0]=f[i+1][j+1][1]*((double)(j+1)/(i+j+2))*((double)(i+1)/(i+j+1)); f[i][j][0]+=f[i][j+2][1]*((double)(j+2)/(i+j+2))*((double)(j+1)/(i+j+1)); //f[i][j][0]可以从上一轮B拿走一只黑鼠扔掉一只黑鼠和拿走一只黑鼠和扔掉一只白鼠转移 //但绝对不能从拿走一只白鼠转移,因为这样游戏就结束了。 if((i|j)) ans+=f[i][j][0]*((double)i/(i+j)); //每步加一次当前的答案。 f[i][j][1]=f[i][j+1][0]*((double)(j+1)/(i+j+1)); //f[i][j][1]只能从上一轮A拿走一只黑鼠转移,因为拿走白鼠已经累计到答案里了 } printf("%.9lf",ans); return 0; }