zoukankan      html  css  js  c++  java
  • POJ2096 Collecting Bugs

    一个软件有s个子系统,会产生n种bug。某人一天发现一个bug,这个bug属于某种bug,发生在某个子系统中。
    求找到所有的n种bug,且每个子系统都找到bug,这样所要的天数的期望。
    需要注意的是:bug的数量是无穷大的,所以发现一个bug,出现在某个子系统的概率是1/s,属于某种类型的概率是1/n。
    数据范围1≤n,s≤2000。
    TL:1s,ML:256Mb

    计算期望E=∑所有可能需要的天数*概率
    s种系统,n种bug,bug数量不限,求在每个子系统中都找到了bug,且每个bug都出现了的期望天数
    思考能够描述状态空间的数组
    在这个状态空间中,有找到了几种bug,和几个子系统中找到了bug两个问题(我们需要注意到,对于这s个子系统,究竟找到了哪种bug这是不重要的,因为题目没有限定在某个系统要找哪种bug,也没有限定某种bug要被找到多少次,为了使期望天数最小,我们贪心的想,每种bug我们只在某个子系统中找到一次,每个子系统只找到一次bug,但不幸的是)。
    这样我们能够设置出这样的dp数组:f[i, j]表示找了i个bug,在j个子系统中找到bug的期望天数
    这样我们可以想到4个情况推导到当前情况,f[i - 1, j], f[i, j - 1], f[i - 1, j - 1], f[i, j]
    但是这样推导过来,我们在当前情况的1天的概率我们是知道的,但是这4中情况的总概率并不等于1,也就是说,在某个期望天数内出现当前状态的概率并不等于1,这意味着可能会有需要2天,3天...的概率,这样问题就变得复杂难算,
    但是我们似乎没有更多的信息支持我们相出一个新的状态,这样我们只能换一种思考方式:

    摘抄:对于期望 DP,我们一般采用逆序的方式来定义状态,即考虑从当前状态到达终点的期望代价。因为在大多数情况下,终点不唯一,而起点是唯一的

    //链接:https://blog.sengxian.com/algorithms/probability-and-expected-value-dynamic-programming

    对于现在什么都不会的身为蒟蒻的我,选择相信大佬,倒着退....这样我们存储的信息就变成了,距离期望天数还有多少天,也就是距离期望天数的剩余天数
    1.在新的系统中找到了旧bug:f[i, j + 1]
    2.在旧的系统中找到了新Bug:f[i + 1, j]
    3.在旧的系统中找到了旧Bug:f[i, j]
    4.在新的系统中找到了新bug:f[i + 1, j + 1]
    由这四个状态向当前情况推导
    对于概率的计算,分别是:
    1.p1 = i * (s - j) / (n * s);
    2.p2 = (n - i) * j / (n * s);
    3.p3 = i * j / n * s;
    4.p4 = (n - i) * (s - j) / (n * s)
    然后根据E(aA+bB+cC+dD+...)=aEA+bEB+....;//a,b,c,d...表示概率,A,B,C...表示状态
    所以最后的dp方程就是:
    f[i, j] = p1 * f[i, j + 1] + p2 * f[i + 1, j] + p3 * f[i, j] + p4 * f[i + 1, j + 1] + 1;
    ==> f[i, j] - p3 * f[i, j] = p1 * f[i, j + 1] + p2 * f[i + 1, j] + p4 * f[i + 1, j + 1] + 1;
    ==> f[i, j] * (1 - p3) = p1 * f[i, j + 1] + p2 * f[i + 1, j] + p4 * f[i + 1, j + 1] + 1;
    ==> f[i, j] = (p1 * f[i, j + 1] + p2 * f[i + 1, j] + p4 * f[i + 1, j + 1] + 1) / (1 - p3);
    初态:f[n][s] = 0;
    末态:f[0][0]

     

     1 #include<bits/stdc++.h>
     2 #define ll long long
     3 #define uint unsigned int
     4 #define ull unsigned long long
     5 using namespace std;
     6 const int maxn = 1100;
     7 double f[maxn][maxn];
     8 int n, s; 
     9 double a, b, c, d;
    10 //f[i, j]表示找了i个bug,在j个子系统中找到bug的期望天数 
    11 inline int read() {
    12     int x = 0, y = 1;
    13     char ch = getchar();
    14     while(!isdigit(ch)) {
    15         if(ch == '-') y = -1;
    16         ch = getchar();
    17     }
    18     while(isdigit(ch)) {
    19         x = (x << 1) + (x << 3) + ch - '0';
    20         ch = getchar();
    21     }
    22     return x * y;
    23 }
    24 
    25 int main() {
    26     memset(f, 0, sizeof(f));
    27     n = read(), s = read();
    28     for(int i = n; i >= 0; --i)
    29         for(int j = s; j >= 0; --j) {
    30             //4种情况:旧的系统中找到了新的bug,旧的系统中找到了旧的bug 
    31             //新的系统中找到了新的bug,新的系统中找到了旧的bug 
    32             if(i == n && j == s) continue;
    33             a = 1.0 * j * (n - i) / (s * n);//旧系统,新bug
    34             b = 1.0 * j * i / (s * n);//旧系统,旧bug
    35             c = 1.0 * (s - j) * i / (s * n);//新系统,旧bug
    36             d = 1.0 * (s - j) * (n - i) / (s * n);//新系统,新bug
    37             f[i][j] = (a * f[i + 1][j] + c * f[i][j + 1] + d * f[i + 1][j + 1] + 1) / (1 - b);  
    38         }
    39     printf("%.4f
    ", f[0][0]);
    40     return 0;
    41 }
  • 相关阅读:
    线段拟合(带拉格朗日乘子,HGL)
    工作到位的标准
    Git的简单使用
    位移
    java日期格式化(util包下转成sql包下)
    java中继承的概念
    工作流驳回到指定连线节点上
    年终个人总结
    实现多条件查询 匹配数据库字段中多个数据
    activiti和SSH项目做整合
  • 原文地址:https://www.cnblogs.com/ywjblog/p/9281220.html
Copyright © 2011-2022 走看看