poj 2096 Collecting Bugs

这个题是一个期望DP题:

假设从a要走到d,a与b,c连通,b,c与d连通,那么从a到d的期望就是就是a到b的概率乘以b到d的期望,加上a到c的概率乘以c到d的期望,再加上花费;

我们注意到这个题的bug是无穷的,那么从每个子程序找到bug的概率是1/s,而属于那种类型的是1/n;

这里我们设dp[i][j]为找到从j种子程序中找到了i中类型;那麽dp[n][s]=0;代表已经到了目标;

那么dp[i][j]与哪几种可能相连,有4种可能,

dp[i][j],代表发现i中bug从j个子程序中找到的;

dp[i+1][j],找到新的种类bug,从j个子程序;

dp[i][j+1],i种类bug,从j+1个子程序;

dp[i+1][j+1];找到新的种类bug,从j+1个子程序;

p1 = i*j/n*s;

p2 = (n-i)*j/n*s;

p3 = i*(s-j)/n*s;

p4 = (n-i)*(s-j)/n*s;

以为期望值E[p1P1 + p2*P2 +...+pn*Pn] = p1E[P1] + p2*E[P2] +...+pn*P[n];

dp[i][j] = 1 + p1*dp[i][j] + p2*dp[i+1][j] + p3*dp[i][j+1] + p4*dp[i+1][j+1];

再把dp[i][j]整理出来就可以了;

View Code
#include<iostream>

#include<cstdio>

#include<cstdlib>

#include<algorithm>

#include<cmath>

#include<queue>

#include<set>

#include<map>

#include<cstring>

#include<vector>

#include<string>

#define LL long long

using namespace std;

double dp[1024][1024];

int main(  )

{

    int n,s;

    while( scanf( "%d %d",&n,&s )==2 )

    {

           dp[n][s] = 0;

           for( int i = n ; i >=0 ; i -- )

               for( int j = s ; j >= 0 ; j -- ){

                   if( i==n && j==s ) continue;

                    dp[i][j] = (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);

            }

       printf( "%.4f\n",dp[0][0] );

    }

    //system( "pause" );

    return 0;

}

 

你可能感兴趣的:(bugs)