CF148D Bag of mice

题目传送门

题目描述

公主和龙🐉从一个初始装有 \(w\) 只白老鼠和 \(b\) 只黑老鼠的袋子中轮流抓老鼠,第一个从袋子里抓出白老鼠的人获胜。每一次龙从袋子里抓出一只老鼠时其他在袋子里的老鼠会变得惊慌,其中的一只会跳出袋子(公主抓老鼠时不会有老鼠跳出)。公主先手。公主获胜的概率是多少?另外,如果袋子里已经没有任何老鼠且没有一个人抓出了一只白老鼠,则龙获胜。自己跳出袋子的老鼠不是被抓出来的(不能决定胜者)。一只老鼠离开袋子后将永不返回袋子中。所有袋子中的老鼠被抓出去的概率是相等的,所有袋子中的老鼠受到惊吓跳出袋子的概率也是相等的。

思路

很适合刚学概率 DP 的人练练手!很有意思。
我们设 f[i][j] 表示在有 i 只白老鼠和 j 只黑老鼠时公主先手的获胜概率,g[i][j] 表示龙🐉先手的获胜概率。于是就有转移:

  • \(f[i][j]\) 为一次就抓到白老鼠和抓到黑老鼠但龙🐉输了的概率和,则 \(f[i][j] = i/(i+j) + j/(i+j) * (1-g[i][j-1])\)
  • \(g[i][j]\) 为一次抓到白老鼠、抓到黑老鼠跑了白老鼠时公主输了、抓到黑老鼠跑了黑老鼠时公主输了的概率和,则\(g[i][j] = i/(i+j) + [j/(i+j)] * [i/(i+j-1)] * (1-f[i-1][j-1]) + [j/(i+j)] * [(j-1)/(i+j-1)] * (1-f[i][j-2])\)

于是一个非常简短的代码就诞生了。

Code

#include<bits/stdc++.h>
using namespace std;
double f[1005][1005],g[1005][1005];
	// f[i][j] 表示 i 只白老鼠和 j 只会给老鼠时公主的获胜概率,g[i][j] 同理。 
int main(){
	int w,b;
	scanf("%d%d",&w,&b);
	for(int i=1;i<=w;i++){
		f[i][0]=g[i][0]=1; //记得处理边界条件。
		for(int j=1;j<=b;j++){
			f[i][j]=1.0*i/(i+j)+1.0*j/(i+j)*(1-g[i][j-1]);
			g[i][j]=1.0*i/(i+j)+1.0*j/(i+j)*i/(i+j-1)*(1-f[i-1][j-1]);
			if(j>=2) g[i][j]+=1.0*j/(i+j)*(j-1)/(i+j-1)*(1-f[i][j-2]); //判断下标是否会越界。
		}
	}
	printf("%.9lf\n",f[w][b]); 
	return 0;
}

\(\sim\) ❀完结撒花❀ \(\sim\)

posted @ 2025-12-18 12:44  404-NoT_FinD  阅读(35)  评论(0)    收藏  举报