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 }

 

posted @ 2018-05-07 18:05  qrfkickit  阅读(187)  评论(0编辑  收藏  举报