【POJ 2096 Collecting Bugs】概率DP求期望

本文探讨了一个关于收集不同类别和子系统bug的数学期望问题。通过建立递推公式,给出了具体的解决方法及实现代码。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

题意:
Ivan每天可以收集一个bug,每个bug属于某个类别和某个子系统,现求收集n种类别和s个子系统的期望天数。
比如bug1属于类别1子系统1,bug2属于类别1子系统2,那么就收集到了1个类别和2个子系统的bug。
题解:
f[i][j]表示已经有i个类别j个子系统的期望天数,那么当前这天找的bug有四种情况:
1.Bug属于已有的类别,已有的子系统,即f[i][j]−>f[i][j]f[i][j] -> f[i][j]f[i][j]>f[i][j], 概率i/n∗j/si/n * j/si/nj/s
2.Bug属于没有的类别,已有的子系统,即f[i−1][j]−>f[i][j]f[i - 1][j] -> f[i][j]f[i1][j]>f[i][j], 概率(1−i/n)∗j/s(1 - i/n) * j/s(1i/n)j/s
3.Bug属于已有的类别,没有的子系统,即f[i][j−1]−>f[i][j]f[i][j - 1] -> f[i][j]f[i][j1]>f[i][j], 概率i/n∗(1−j/s)i/n * (1 - j/s)i/n(1j/s)
4.Bug属于没有的类别,没有的子系统,即f[i−1][j−1]−>f[i][j]f[i - 1][j - 1] -> f[i][j]f[i1][j1]>f[i][j], 概率(1−i/n)∗(1−j/s)(1 - i/n) * (1 - j/s)(1i/n)(1j/s)
f[i][j]=i/n∗j/s∗f[i][j]+(1−i/n)∗j/s∗f[i−1][j]+i/n∗(1−j/s)∗f[i][j−1]+(1−i/n)∗(1−j/s)∗f[i−1][j−1]f[i][j] = i/n * j/s * f[i][j] + (1 - i/n) * j/s * f[i - 1][j] + i/n * (1 - j/s) * f[i][j - 1] + (1 - i/n) * (1 - j/s) * f[i - 1][j - 1]f[i][j]=i/nj/sf[i][j]+(1i/n)j/sf[i1][j]+i/n(1j/s)f[i][j1]+(1i/n)(1j/s)f[i1][j1]
-> f[i][j]=(n∗s+(n−i)∗j∗f[i−1][j]+n∗(s−j)∗f[i][j−1]+(n−i)∗(s−j)∗f[i−1][j−1])/(n∗s−i∗j)f[i][j] = (n * s + (n - i) * j * f[i - 1][j] + n * (s - j) * f[i][j - 1] + (n - i) * (s - j) * f[i - 1][j - 1])/(n * s - i * j)f[i][j]=(ns+(ni)jf[i1][j]+n(sj)f[i][j1]+(ni)(sj)f[i1][j1])/(nsij)
我们所求的答案为f[n][s],但是这里i=n,j=si = n, j = si=n,j=s会使分母(n∗s−i∗j)(n * s - i * j)(nsij)为0,故要倒着推。
f[n][s]=0f[n][s] = 0f[n][s]=0, 递推公式为f[i][j]=(n∗s+(n−i)∗j∗f[i+1][j]+i∗(s−j)∗f[i][j+1]+(n−i)∗(s−j)∗f[i+1][j+1])/(n∗s−i∗j)f[i][j] = (n * s + (n - i) * j * f[i + 1][j] + i * (s - j) * f[i][j + 1] + (n - i) * (s - j) * f[i + 1][j + 1]) / (n * s - i * j)f[i][j]=(ns+(ni)jf[i+1][j]+i(sj)f[i][j+1]+(ni)(sj)f[i+1][j+1])/(nsij), 所求答案为f[0][0]f[0][0]f[0][0]
代码:

const int MAX = 1e3 + 10;
int n, s;
double f[MAX][MAX];

int main() {
	scanf("%d%d", &n, &s);
	f[n][s] = 0;
	for (int i = n; i >= 0; i--)
		for (int j = s; j >= 0; j--) {
			if (i == n && j == s)continue;
			f[i][j] = (n * s + (n - i) * j * f[i + 1][j] + i * (s - j) * f[i][j + 1] + (n - i) * (s - j) * f[i + 1][j + 1]) / (n * s - i * j);
		}
	printf("%.4lf\n", f[0][0]);
	return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值