概率题
题意:输入case数,每组case两个数字,表示A的点数和B的点数,他们玩游戏,每个人赢的概率都是0.5。输的人要将自己的一部分点数给对方,给的点数是min(na,nb)。例如na=3,nb=2
如果A赢了,B要给2点给A,即全部给完。如果B赢了,A要给2点给B,A变为1,B变为4。一个人的点数为0,那么游戏结束了。题目要你输出两个数学期望,第一个是,这个游戏要结束,要玩多少局的数学期望,另一个是A赢的概率
这题一开始看觉得是期望DP,后来想想也可以不写DP,能把状态表达出来即可。
设一个状态(n,m,c)表示A现在的点数是n,B的点数是m,已经玩了c局。那么游戏结束的状态就是(n,0,c)或者(0,m,c)
而玩了c局,游戏结束,这个概率是多少,就是(0.5)^c , 因为每次玩无论怎样概率都是0.5
而这个游戏是可以无限玩下去的(这个很容易想到,其中sample2就可以无限玩下去),所以算这个数学期望和概率是没有尽头的,但是输出说了,精确到10^-5,当游戏局数很大是,不会再对数学期望和概率产生大的影响,在精度范围内
所以搜索的时候,可以限制深度,即设定一个局数,超过了这个局数就返回不要继续算下去
而每到游戏结束的时候,就可以计算数学期望和概率
数学期望 = sum(xi*pi)
概率 = sum(pi)
#include <cstdio> #include <cstring> #define LIM 40 #define min(a,b) ((a)<(b)?(a):(b)) double EX[2]; double cal(int c) { double ans = 1; for(int i=1; i<=c; i++) ans *= 0.5; return ans; } void dfs(int n ,int m , int c) { if(c > LIM) return ; //限深度搜索 if( n==0 || m==0) //游戏结束 { double p = cal(c); EX[0] += c*p; if(m==0) EX[1] += p; return ; } int res = min(n,m); dfs(n-res , m+res , c+1); dfs(n+res , m-res , c+1); } int main() { int T; scanf("%d",&T); for(int t=1; t<=T; t++) { int n,m; scanf("%d%d",&n,&m); EX[0]=EX[1]=0; dfs(n,m,0); printf("Case %d: %.6lf %.6lf\n",t,EX[0],EX[1]); } return 0; }