天天看點

POJ 2096(Collecting Bugs)

題意:某人喜歡收集 Bug ,現給定 n 個 Bug 和 s 個程式 ,求在 s 個程式中找全 n 個 Bug 并且每一個程式都至少找到

一個 Bug 的機率

分析:設 dp[ i ][ j ] 表示找到了i 種 Bug ,并且 j 個程式都至少找到一個 Bug 的機率,則 dp[ i ][ j ]的組成有以下四種情況:

① dp[ i ][ j ]  * 

POJ 2096(Collecting Bugs)

  *  

POJ 2096(Collecting Bugs)

        //找到的 Bug 屬于已經找到的 i 種 Bug 之一,并且出現在 j 個程式之中

② dp[ i+1 ][ j ]  *  ( 1 - 

POJ 2096(Collecting Bugs)

)  *  

POJ 2096(Collecting Bugs)

          //找到的 Bug 不屬于已經找到的 i 種 Bug ,并且出現在 j 個程式之中

③ dp[ i ][ j+1 ]  *  

POJ 2096(Collecting Bugs)

  *  ( 1 - 

POJ 2096(Collecting Bugs)

)         //找到的 Bug 屬于已經找到的 i 種 Bug 之一,但在 j 個程式之中沒有出現

④ dp[ i+1 ][ j+1 ]  *  ( 1 - 

POJ 2096(Collecting Bugs)

)  *  ( 1 - 

POJ 2096(Collecting Bugs)

)       //找到的 Bug 不屬于已經找到的 i 種 Bug ,且在 j 個程式之中沒有出現

綜合以上四種情況,可以推出轉移方程:

dp[ i ][ j ] =  dp[ i ][ j ]  *  

POJ 2096(Collecting Bugs)

  *  

POJ 2096(Collecting Bugs)

   +  dp[ i+1 ][ j ]  *  ( 1 - 

POJ 2096(Collecting Bugs)

)  *  

POJ 2096(Collecting Bugs)

   +  dp[ i ][ j+1 ]  *  

POJ 2096(Collecting Bugs)

  *  ( 1 - 

POJ 2096(Collecting Bugs)

)   

                                                                                                                                     +  dp[ i+1 ][ j+1 ]  *  ( 1 - 

POJ 2096(Collecting Bugs)

)  *  ( 1 - 

POJ 2096(Collecting Bugs)

)

移項可得 :

dp[ i ][ j ] = ( dp[ i+1 ][ j ]  *  ( 1 - 

POJ 2096(Collecting Bugs)

)  * 

POJ 2096(Collecting Bugs)

   +  dp[ i ][ j+1 ]  *  

POJ 2096(Collecting Bugs)

  *  ( 1 - 

POJ 2096(Collecting Bugs)

)   +  dp[ i+1 ][ j+1 ]  *  ( 1 - 

POJ 2096(Collecting Bugs)

)  *  ( 1 - 

POJ 2096(Collecting Bugs)

) )

                                                                                                                                     /  (1 -

POJ 2096(Collecting Bugs)

  *  

POJ 2096(Collecting Bugs)

              =  ( 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 - i*j )

代碼:

#include<cstdio>
#include<iostream>
using namespace std;

const int N = 1005;

double dp[N][N];
int n,s;

int main()
{
	scanf("%d%d",&n,&s);
	dp[n][s]=0;
	double a,b,c,d;
	for(int i=n;i>=0;i--)
	for(int j=s;j>=0;j--)
	{
		if(i==n&&j==s) continue;
		a = (double) (n-i)*j;
		b = (double) i*(s-j);
		c = (double) (n-i)*(s-j);
		d = (double) n*s-i*j;
		dp[i][j]=(dp[i+1][j]*a+dp[i][j+1]*b+dp[i+1][j+1]*c+n*s)/d;
	} 
	printf("%.4f\n",dp[0][0]);  
	return 0;
}