题目链接:https://cn.vjudge.net/contest/247409#problem/B
题目大意:
一个软件有s个子系统,会产生n种bug
某人一天发现一个bug,每个bug属于一个子系统,属于一个分类
每个bug属于某个子系统的概率是1/s,属于某种分类的概率是1/n
求发现n种bug,且每个子系统都发现了bug的天数的期望。
题目思路:
f[i][j]表示现在已经找到的bug有i种,属于j个系统,找完剩下所需bug的期望天数。
已知:f[n][s]=0, 而要求的答案是f[0][0]
每天有四种情况:
发现一个bug属于已经有的i个分类和j个系统。(i/n)*(j/s) * (f[i][j] +1)
发现一个bug属于已有的分类,不属于已有的系统。(i/n)*(1-j/s) * (f[i][j+1]+1)
发现一个bug属于已有的系统,不属于已有的分类。 (1-i/n)*(j/s) * (f[i+1][j]+1)
发现一个bug不属于已有的系统,不属于已有的分类。 (1-i/n)*(1-j/s) *(f[i+1][j+1]+1)
f[i][j] = (i/n)*(j/s) * (f[i][j] +1) + (i/n)*(1-j/s) * (f[i][j+1]+1) + (1-i/n)*(j/s) * (f[i+1][j]+1) + (1-i/n)*(1-j/s) *(f[i+1][j+1]+1)
最后因为左右两边都要f[i][j],化简一下即可
#include <iostream>
#include<cstdio>
#include<algorithm>
#include<cmath>
#include<cstring>
#include<string.h>
using namespace std;
const int maxn=1200;
/*dp[i][j] = (i/n)*(j/s) * (dp[i][j] +1) + (i/n)*(1-j/s)*(dp[i][j+1]+1)+
(1-i/n)*(j/s)*(dp[i+1][j]+1)+(1-i/n)*(1-j/s)*(dp[i+1][j+1]+1)*/
int n,s;
double dp[maxn][maxn];
int main()
{
while(~scanf("%d%d",&n,&s))
{
memset(dp,0,sizeof dp);
for(int i=n;i>=0;i--)
{
for(int j=s;j>=0;j--)
{
if(i==n&&j==s)continue;
dp[i][j]=(1.0*i/n)*(1.0*j/s)+1.0*(1.0*i/n)*(1-1.0*j/s)*(dp[i][j+1]+1)
+(1-1.0*i/n)*(1.0*j/s)*(dp[i+1][j]+1)+(1-1.0*i/n)*(1-1.0*j/s)*(dp[i+1][j+1]+1);
dp[i][j]=dp[i][j]/(1.0-(1.0*i/n)*(1.0*j/s));
}
}
printf("%.4f\n",dp[0][0]);
}
return 0;
}