poj 2096 Collecting Bugs
题意:
一个公司的系统有n种bug,s个子系统。
一个人找一个bug需要找一天。
找到每种是等概率的,找到一个子系统是等概率的。
现在,他需要在每个子系统中找到一个bug,并且找到n种bug,问期望的天数。
思路:
概率dp入门题,一般来说,期望是逆推的。
设dp[i][j]表示找到了i种bug,找完j个系统之后还需要的天数。
显然dp[n][s] = 0,因为不需要找了。
于是向前逆推,从明天推到今天,显然明天花的时间要多一天:
今天找到i种bug,找完了j种系统,可能有几种情况
dp[i+1][j],明天找到了i+1种bug,找完j个子系统,概率是(n-i) * j / (s*n);
dp[i][j+1],明天找到了i种bug,找完j+1个子系统,概率是i * (s-j) / (s*n);
dp[i+1][j+1],明天找到了i+1种bug,找完j个子系统,概率是(n-i) * (s-j) / (s*n);
dp[i][j],明天找到了i种bug,找完j个子系统,概率是i * j / (s*n);
所以,就有如下的期望递推式子:
dp[i][j] = dp[i][j] * i * j / (s*n) + dp[i+1][j+1] * i * (s-j) / (s*n) + dp[i][j+1] * i * (s-j) / (s*n) + dp[i+1][j] * (n-i) * j / (s*n) + 1。
整理之后得到:
dp[i][j] = (dp[i][j] * i * j + dp[i+1][j+1] * i * (s-j) +dp[i][j+1] * i * (s-j) + dp[i+1][j] * (n-i) * j + s * n) / (s * n - i * j)。
倒着dp就行了,答案就是dp[0][0]。
代码:
1 #include <stdio.h> 2 #include <string.h> 3 #include <algorithm> 4 using namespace std; 5 const int N = 1e3 + 5; 6 double dp[N][N]; 7 int main() 8 { 9 int n,s; 10 scanf("%d%d",&n,&s); 11 dp[n][s] = 0; 12 for (int i = n;i >= 0;i--) 13 { 14 for (int j = s;j >= 0;j--) 15 { 16 if (i == n && j == s) continue; 17 double &ans = dp[i][j]; 18 ans = (dp[i+1][j]*(n-i)*j+dp[i][j+1]*i*(s-j)+dp[i+1][j+1]*(n-i)*(s-j)+n*s) / (n*s-i*j); 19 } 20 } 21 printf("%.4f\n",dp[0][0]); 22 return 0; 23 }