OJ题目 : click here ~~~
大概题意:
题目读起来有点累。有n个种类 , s个子系统 。每天找1个bug ,这个bug必属于某个种类和某个子系统,且概率相等,即为1/n , 1/s。给 n , s , 求找到属于n个种类 , s个系统的的bug,需要天数的期望。
定义dp[ i ][ j ] 为已找到属于 i 个种类 ,j个系统的bug , 距离目标还差的天数的期望。
有dp[ i ][ j ] ,找到下一个bug , 则,
1. 这个bug 属于已找到的 i 个种类别中的一个 , 且属于已找到的 j 个子系统中的一个 , 此时dp[ i ][ j ] , 概率为p1 = i/n * j / s;
2. 这个bug是新的1类 , 但属于已找到的j个子系统中的一个,此时dp[ i + 1][ j ] , 概率为p2 = (1 - i/n) * j / s;
3. 这个bug属于已经找到的i个类别中的一个 ,但是新的1个子系统 ,此时dp[ i ][ j + 1 ] , 概率为p3 = i/n *(1 - j / s);
4. 这个bug是新的1类,且是新的1个子系统,此时dp[ i + 1 ][ j + 1 ] , 概率为p4 = (1 -i/n) *(1 - j / s)
状态转移方程:dp[ i ][ j ] = p1 * dp[ i ][ j ] + p2 *dp[ i + 1 ][ j ] + p3 * dp[ i ][ j + 1 ] + p4 * dp[i + 1][j + 1]+ 1;(找这个bug,需要一天,所以不能忘记加1)
不能将未知量当成已知使用 , so 整理方程,将dp[ i ][ j ]放在左边 ;
AC_CODE
double dp[1002][1002];
int main()
{
int n , s;
while(scanf("%d%d",&n,&s) != EOF)
{
int i , j;
double p1 , p2 , p3 , p4;
dp[n][s] = 0;
for(i = n;i >= 0;i--)
{
for(j = s;j >= 0;j--)
{
if(i == n&&j == s)
continue;
p1 = (1.0 * i * j)/(n * s);
p2 = (n - i) * 1.0 * j/(n * s);
p3 = 1.0 * i * (s - j)/(n * s);
p4 = 1.0 * (n - i) * (s - j)/(n * s);
dp[i][j] = (p2 * dp[i + 1][j] + p3 * dp[i][j + 1] + p4 * dp[i + 1][j + 1] + 1)/(1 - p1);
}
}
printf("%.4lf\n",dp[0][0]);
}
return 0;
}