| Time Limit: 10000MS | Memory Limit: 64000K | |
| Total Submissions: 2026 | Accepted: 971 | |
| Case Time Limit: 2000MS | Special Judge |
Description
Input
Output
Sample Input
1 2
Sample Output
3.0000
Source
解题思路:
一个软件有 s 个子系统,存在 n 种 bug。某人一天能找到一个 bug。问,在这个软件中找齐 n 种 bug,并且每个子系统中至少包含一个 bug 的时间的期望值(单位:天)。注意:bug 是无限多的,每个 bug 属于任何一种 bug 的概率都是 1/n;出现在每个系统是等可能的,为 1/s。
令 ex[i][j] 表示已经找到了 i 种 bug,且 j 个子系统至少包含一个 bug,距离完成目标需要的时间的期望。
这样说有点不好理解。换一种方法。有n个bug1有s个bug2,ex[i][j]表示为已经发现了i个bug1,j个bug2,离目标发现s个bug1,n个bug2还需要的期望天数。这样所求就是ex[0][0],而ex[n][s]则为0,因为已经全部发现,不需要额外的天数了。到下一天,可能产生四种情况,ex[i][j],没有发现任何bug,ex[i+1][j],发现一个bug1, ex[i][j+1],发现一个bug2,ex[i+1][j+1],发现两个bug,那么
ex[i][j]= 1+p1*ex[i][j] +p2*ex[i+1][j]+p3*ex[i][j+1]+p4*ex[i+1][j+1] ,需要加1,因为是下一天
(后来右想了想,为什么由ex[i][j]可以推出四种情况,然后就可以说ex[i][j]=后面的式子呢,其实这里ex[i][j] “ 实际上”,这里说的实际,是在实际工作中,你要发现两个bug,肯定首先得发现一个bug吧,所以ex[i][j]其实是由后面那四个式子推出来的,因为我们这里ex[i][j]表示的意义就是距离完成目标还需要的时间期望。)
p1= (i/n)*(j/s)=(i*j)/(n*s)
p2=((n-i)/n)*(j/s)=(n-i)*j/(n*s)
p3=(i/n)*((s-j)/s)=i*(s-j)/(n*s)
p4=((n-i)/n)*((s-j)/s)=(n-i)*(s-j)/(n*s)
这样整理出来就是
ex[i][j]=1+ (i*j)/(n*s)*ex[i][j]+(n-i)*j/(n*s)*ex[i+1][j]+i*(s-j)/(n*s)*ex[i][j+1]+(n-i)*(s-j)/(n*s)*ex[i+1][j+1]
右边(i*j)/(n*s)*ex[i][j]移到左边合并同类项。得到:
ex[i][j]=( 1+(n-i)*j/(n*s)*ex[i+1][j]+i*(s-j)/(n*s)*ex[i][j+1]+(n-i)*(s-j)/(n*s)*ex[i+1][j+1] ) / (1-(i*j)/(n*s))
参考资料:
http://kicd.blog.163.com/blog/static/126961911200910168335852/
代码:
#include <iostream>
#include <string.h>
#include <iomanip>
using namespace std;
const int maxn=1005;
double ex[maxn][maxn];
int main()
{
memset(ex,0,sizeof(ex));
int n,s;
cin>>n>>s;
double m=n*s*1.0;
for(int i=n;i>=0;i--)
for(int j=s;j>=0;j--)
{
if(i==n&&j==s)
continue;
ex[i][j]=(1+((n-i)*(s-j)/m)*ex[i+1][j+1]+((n-i)*j/m)*ex[i+1][j]+(i*(s-j)/m)*ex[i][j+1])/(1-i*j/m);
}
cout<<setiosflags(ios::fixed)<<setprecision(4)<<ex[0][0];
return 0;
}
[ACM] poj 2096 Collecting Bugs (概率DP,期望),布布扣,bubuko.com
[ACM] poj 2096 Collecting Bugs (概率DP,期望)
原文:http://blog.csdn.net/sr_19930829/article/details/25052227