[POJ2096]Collecting Bugs

做题时间:2022.8.9

\(【题目描述】\)

一个软件有 \(n(n\leq 1000)\) 个子系统,会产生 \(s(s\leq 1000)\) 种 bug。某人一天发现一个 bug,这个 bug 属于某种 bug 分类,也属于某个子系统。每个 bug 属于某个子系统的概率是 \(\frac{1}{n}\) ,属于某种 bug 分类的概率是 \(\frac{1}{s}\) 。求发现 \(n\) 种 bug,且\(s\) 个子系统都找到 bug 的期望天数。

\(【输入格式】\)

一行两个整数表示 \(n,s\)

\(【输出格式】\)

一行一个整数表示答案

\(【考点】\)

期望DP

\(【做法】\)

考虑期望DP,终点确定,求期望步数,为求方便采取倒序遍历,定义 \(f_{i,j}\) 表示已经找到了 \(i\) 种bug, \(j\) 个子系统的bug,到达目标的期望天数。对于当前bug,对于是否在已找到的bug类型、已找到bug的子系统中分四种情况,有方程:

\[f_{i,j}=f_{i,j}\times\frac{i}{n}\times \frac{j}{s}+f_{i+1,j}\times (1-\frac{i}{n})\times \frac{j}{s}+f_{i,j+1}\times \frac{i}{n}\times (1-\frac{j}{s})+f_{i+1,j+1}\times (1-\frac{i}{n})\times (1-\frac{j}{s})+1 \]

\(f_{i,j}\) 项移到左边有:

\[\large f_{i,j}=\frac{f_{i,j+1}\times i\times (s-j)+f_{i+1,j}\times j\times (n-i)+f_{i+1,j+1}\times (n-i)\times (s-j)+n\times s}{ns-ij} \]

最后答案就是 \(f_{0,0}\) 倒序转移即可。

\(【代码】\)

#include<cstdio>
#include<iomanip>

using namespace std;
const int N=1e3+50;
int n,s;
double f[N][N];
int main()
{
	scanf("%d%d",&n,&s);
	for(int i=n;i>=0;i--){
		for(int j=s;j>=0;j--){
			if(i!=n||j!=s) f[i][j]=(f[i][j+1]*i*(s-j)+
			f[i+1][j]*j*(n-i)+f[i+1][j+1]*(n-i)*(s-j)+n*s)/(n*s-i*j);
		}
	}
	printf("%lf\n",f[0][0]);
	return 0;
}
posted @ 2022-08-09 17:12  lxzy  阅读(24)  评论(0)    收藏  举报