题目链接:http://poj.org/problem?id=2096
题意:一道入门的概率dp题目。一个系统有n种bug和s个子系统,bug的数量是无限的,每次每天可以从s个子系统中找到一个bug,每种bug的概率都是相等的,现求s个子系统中找到n种bug的平均天数,要求每个子系统中至少找到一种bug
思路:dp[i][j] 表示已经在j个子系统中找到了i种bug,剩余所需要的平均天数。
显然dp[n][s] = 0,已经在s个子系统中找到了n种bug,所以等于已经完成了任务,即最终要求的是dp[0][0]
那么dp[i][j] 可以转移的状态为四种:
①i,j+1;所发现的bug在新子系统中,此前已经已经发现相同的种类的bug;
②i+1,j+1;所发现的bug在新子系统中,此前还未发现过此类bug;
③i,j;所发现的bug在旧子系统中,此前已经已经发现相同的种类的bug;
④i+1,j;所发现的bug在旧子系统中,此前还未发现过此类bug;
以上四种可能性发生的概率分别可以计算.
其转移方程就是 dp[i][j] = 1 + dp[i+1][j] * p1 + dp[i+1][j+1] * p2 + dp[i][j] * p3 + dp[i][j+1] * p4; //p1....p4分别是各个状态的概率
把等式右边的dp[i][j]*p3移到右边,整理得:
dp[i][j] = (1.0+ dp[i+1][j]*p2 + dp[i][j+1]*p3 + dp[i+1][j+1]*p4)/(1.0-p1);
AC代码:
#include<iostream>
#include<vector>
#include<cstring>
#include<algorithm>
#include<queue>
#include<cstdio>
#define inf 0x3f3f3f3f
using namespace std;
double dp[1005][1005];
typedef long long ll;
int main(){
ios::sync_with_stdio(false);
cin.tie(0),cout.tie(0);
int n,s;
while(scanf("%d%d",&n,&s)!=EOF){
memset(dp,0,sizeof(dp));
for(int i = n;i>=0;i--){
for(int j = s;j>=0;j--){
if(i == n && j == s) continue;
double p1 = 1.0*i/n*j/s;
double p2 = 1.0*(n-i)/n*j/s;
double p3 = 1.0*i/n*(s-j)/s;
double p4 = 1.0*(n-i)/n*(s-j)/s;
dp[i][j] = (1.0+ dp[i+1][j]*p2 + dp[i][j+1]*p3 + dp[i+1][j+1]*p4)/(1.0-p1);
}
}
printf("%.4f
",dp[0][0]);
}
return 0;
} //