小记:dp好像分好多种,看到了斜率dp,概率dp,树形dp,。。。今天遇到了一个概率dp题,不晓得怎么入手。然后百度之,原来是概率dp,瞬间觉得好高端,看也看不懂,于是想着看能找点入门题做下。从网上找了一道,就是此题了。。。
题目大意:有一个程序,有n种bug和m个子系统,当找到一个bug时,它只会在一个系统。当然也可能你在其它系统也可以找到这样的bug,但是那是在找到另一个bug的时候,虽然两个是一种。规定一天只会找到一个bug。问,找到n种bug,且分布在m个子系统中的期望天数。
题解:因为每天都有一个,所以bug是无穷多个的。因此,每天找到一个bug它是某种类型的概率是1/n,在某个系统找到的概率是1/m。
令dp[i][j] 表示为找到了i种bug,分布在j个子系统中时,要到到目标状态所需要的期望天数。
很显然dp[n][m] = 0,而dp[0][0]就是我们要求的目标状态。
当我们找到了一个bug时,有四种情况可能出现;
dp[i][j],这个bug是原来i种就有的,且也在原来的j个子系统中
dp[i+1][j] ,这个bug是原来i种里所没有的,但在原来的j个子系统中
dp[i][j+1],这个bug在原来的i种就有的,但不在原来的j个子系统中
dp[i+1][j+1],这个bug是原来i种里所没有的,但也不在原来的j个子系统中
每一种发生的概率为:
p1 = i*j/(n*m)
p2 = (n-i)*j/(n*m)
p3 = i*(m-j)/(n*m)
p4 = (n-i)*(m-j)/(n*m)
根据期望的性质(在里面相加等于在各个分别期望相加),可得
dp[i,j] = p1*dp[i,j] + p2*dp[i+1,j] + p3*dp[i,j+1] + p4*dp[i+1,j+1] + 1
= ( 1 + p2*dp[i+1,j] + p3*dp[i,j+1] + p4*dp[i+1,j+1] )/( 1-p1 )
= ( n*s + (n-i)*j*dp[i+1,j] + i*(s-j)*dp[i,j+1] + (n-i)*(s-j)*dp[i+1,j+1] )/( n*s - i*j )
代码:
#include <iostream> #include <cstdio> #include <string> #include <map> #include <cstring> using namespace std; const int MAX_ = 1010; double dp[MAX_][MAX_]; int main() { int n,m; while(~scanf("%d%d",&n,&m)) { dp[n][m] = 0.0; for(int i = n; i >= 0; i--){ for(int j = m; j >= 0; j--){ if(i == n && j== m)continue; dp[i][j] = (n*m + (n-i)*j*dp[i+1][j] + i * (m-j) *dp[i][j+1] + (n-i) * (m- j) *dp[i+1][j+1])/(n*m -i*j); } } printf("%.4lf\n",dp[0][0]); } return 0; }