• poj 2096 Collecting Bugs


    题意:

    一个公司的系统有n种bug,s个子系统。

    一个人找一个bug需要找一天。

    找到每种是等概率的,找到一个子系统是等概率的。

    现在,他需要在每个子系统中找到一个bug,并且找到n种bug,问期望的天数。

    思路:

    概率dp入门题,一般来说,期望是逆推的。

    设dp[i][j]表示找到了i种bug,找完j个系统之后还需要的天数。

    显然dp[n][s] = 0,因为不需要找了。

    于是向前逆推,从明天推到今天,显然明天花的时间要多一天:

    今天找到i种bug,找完了j种系统,可能有几种情况

    dp[i+1][j],明天找到了i+1种bug,找完j个子系统,概率是(n-i) * j / (s*n);

    dp[i][j+1],明天找到了i种bug,找完j+1个子系统,概率是i * (s-j) / (s*n);

    dp[i+1][j+1],明天找到了i+1种bug,找完j个子系统,概率是(n-i) * (s-j) / (s*n);

    dp[i][j],明天找到了i种bug,找完j个子系统,概率是i * j / (s*n);

    所以,就有如下的期望递推式子:

    dp[i][j] = dp[i][j] * i * j / (s*n) + dp[i+1][j+1] * i * (s-j) / (s*n) + dp[i][j+1] * i * (s-j) / (s*n) + dp[i+1][j] * (n-i) * j / (s*n) + 1

    整理之后得到:

    dp[i][j] = (dp[i][j] * i * j + dp[i+1][j+1] * i * (s-j) +dp[i][j+1] * i * (s-j) + dp[i+1][j] * (n-i) * j + s * n) / (s * n - i * j)。

    倒着dp就行了,答案就是dp[0][0]。

    代码:

     1 #include <stdio.h>
     2 #include <string.h>
     3 #include <algorithm>
     4 using namespace std;
     5 const int N = 1e3 + 5;
     6 double dp[N][N];
     7 int main()
     8 {
     9     int n,s;
    10     scanf("%d%d",&n,&s);
    11     dp[n][s] = 0;
    12     for (int i = n;i >= 0;i--)
    13     {
    14         for (int j = s;j >= 0;j--)
    15         {
    16             if (i == n && j == s) continue;
    17             double &ans = dp[i][j];
    18             ans = (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) / (n*s-i*j);
    19         }
    20     }
    21     printf("%.4f
    ",dp[0][0]);
    22     return 0;
    23 }
  • 相关阅读:
    哈夫曼树及哈夫曼编码
    01背包问题
    Java IO
    Java对象的复制三种方式
    TCP三次握手和四次挥手
    轻量级Java Web框架的实现原理
    Java并发
    消息队列
    赋值、浅拷贝、深拷贝
    Python文件操作(txtxlsxcsv)及os操作
  • 原文地址:https://www.cnblogs.com/kickit/p/9004152.html
Copyright © 2020-2023  润新知