/*
dp求期望
逆着递推求解
题意:
一个软件有s个子系统,会产生n种bug
某人一天发现一个bug,这个bug属于一个子系统,属于一个分类
每个bug属于某个子系统的概率是1/s,属于某种分类的概率是1/n
问发现n种bug,每个子系统都发现bug的天数的期望。
求解:
dp[i][j]表示已经找到i种bug,j个系统的bug,达到目标状态的天数的期望
dp[n][s]=0,dp[0][0]为所求答案
dp[i][j]由四种状态转化而来
1:dp[i][j] 发现一个状态已有i个分类j个系统 概率p1=i/n*j/s
2: dp[i+1][j] 发现有未属于这个分类,但属于这个系统的bug 概率p2=(1-i/n)*j/s
3: dp[i][j+1] 发现属于这个系统,但不属于这个分类的bug 概率p3=i/n*(1-j/s)
4: dp[i+1][j+1] 发现为属于这个系统且不属于这个分类的bug 概率p4=(1-i/n)*(1-j/s)
所以:dp[i][j] = p1*dp[i][j] + p2*dp[i+1][j] + p3*dp[i][j+1] + p4*dp[i+1][j+1] + 1;
化简得:
dp[i][j]=(dp[i+1][j]*(n*j-i*j)+dp[i][j+1]*(i*s-i*j)+dp[i+1][j+1]*(n*s-j*n-i*s+i*j)+n*s)/(n*s-i*j);
*/
# include <stdio.h>
# include <algorithm>
# include <string.h>
# include <iostream>
using namespace std;
double dp[1010][1010];
int main()
{
int n,s,i,j;
while(~scanf("%d%d",&n,&s))
{
// memset(dp,0,sizeof(dp));
dp[n][s]=0;
for(i=n; i>=0; i--)
{
for(j=s; j>=0; j--)
{
if(i==n&&j==s)
continue;
dp[i][j]=(dp[i+1][j]*(n*j-i*j)+dp[i][j+1]*(i*s-i*j)+dp[i+1][j+1]*(n*s-j*n-i*s+i*j)+n*s)/(n*s-i*j);
}
}
printf("%.4lf\n",dp[0][0]);
}
return 0;
}
poj 2096 Collecting Bugs (概率dp)
最新推荐文章于 2018-12-20 11:17:07 发布