题目大意:
一个人受雇于某公司要找出某个软件的bugs和subcomponents,这个软件一共有n个bugs和s个subcomponents,每次他都能同时随机发现1个bug和1个subcomponent,问他找到所有的bugs和subcomponents的期望次数。
这道题目要用期望dp来进行统计
假设已经找到i个bug和j个subcomponents,这个状态记为dp[i][j],那么下次查找会出现4种状态:dp[i][j],dp[i+1][j],dp[i][j+1],dp[i+1][j+1]
这四种状态的概率为 i*j*1.0/n/s , (n-i)*j*1.0/n/s , i*(s-j)*1.0/n/s , (n-i)*(s-j)*1.0/n/s
那么每到下一种 状态步数要加1,那么我们领dp[i][j]为到达全部找完bug和subcomponents的数学期望,亦可理解为,在这个状态还需多少步能完成任务
这样我们就可以得到公式:
dp[i][j] = 1 + i*j*1.0/n/s * dp[i][j] + (n-i)*j*1.0/n/s * dp[i+1][j] + i*(s-j)*1.0/n/s * dp[i][j+1] + (n-i)*(s-j)*1.0/n/s * dp[i+1][j+1]
那么我们就可以通过后面的状态不断递推来找到前面的状态的值就行了
我们可以很容易知道dp[n][s] = 0;
为了方便计算,不用排除特殊情况,那么我们就将dp[n+1][1]~dp[n+1][s] dp[1][1+s]~dp[n][s+1]设为0作为初始化
然后从后往前不断完善这个矩阵的dp[][]值
最后输出dp[0][0]就是我们要求的值
1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 using namespace std; 5 #define N 1005 6 double dp[N][N]; 7 int main() 8 { 9 int n,m; 10 while(~scanf("%d%d",&n,&m)){ 11 for(int i=1;i<=n+1;i++) 12 dp[i][m+1]=0; 13 14 for(int i=1;i<=m+1;i++) 15 dp[n+1][i]=0; 16 17 dp[n][m]=0; 18 19 for(int i=n;i>=0;i--){ 20 for(int j=m;j>=0;j--){ 21 if(i==n&&j==m) 22 continue; 23 double tmp = 1 + i*(m-j)*1.0/n/m * dp[i][j+1] + (n-i)*j*1.0/m/n * dp[i+1][j] + (n-i)*(m-j)*1.0/m/n * dp[i+1][j+1]; 24 dp[i][j] = tmp / (1-i*j*1.0/m/n); 25 } 26 } 27 28 printf("%.4f\n",dp[0][0]); 29 } 30 return 0; 31 }
时间: 2024-10-10 14:05:28