这个题是一个期望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]整理出来就可以了;
#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; }