题目链接

题意:

一个人受雇于某公司要找出某个软件的bugs和subcomponents,这个软件一共有n个bugs和s个subcomponents,每次他都能同时随机发现1个bug和1个subcomponent,问他找到所有的bugs和subcomponents的期望次数。

一个软件有s个子系统,会产生n种bug
某人一天发现一个bug,这个bug属于一个子系统,属于一个分类
每个bug属于某个子系统的概率是1/s,属于某种分类的概率是1/n
问发现n种bug,每个子系统都发现bug的天数的期望。

分析:

期望倒着推,概率正着推。

dp[i][j]表示已经找到i种bug,并存在于j个子系统中,要达到目标状态的天数的期望。
显然,dp[n][s]=0,因为已经达到目标了。而dp[0][0]就是我们要求的答案。
dp[i][j]状态可以转化成以下四种:
dp[i][j] 发现一个bug属于已经找到的i种bug和j个子系统中
dp[i+1][j] 发现一个bug属于新的一种bug,但属于已经找到的j种子系统
dp[i][j+1] 发现一个bug属于已经找到的i种bug,但属于新的子系统
dp[i+1][j+1]发现一个bug属于新的一种bug和新的一个子系统
以上四种的概率分别为:
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(aA+bB+...) = aE(A) + bE(B) +...
所以:
dp[i,j] = p1*dp[i,j] + p2*dp[i+1,j] + p3*dp[i,j+1] + p4*dp[i+1,j+1] + 1;

移项整理得:
dp[i,j] = ( 1 + p2*dp[i+1,j] + p3*dp[i,j+1] + p4*dp[i+1,j+1] )/( 1-p1 )

= ( 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 )

 #include <iostream>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <cmath>
#include <algorithm>
#define LL __int64
const int maxn = +;
using namespace std;
double d[maxn][maxn]; int main()
{
int n, s, i, j;
while(~scanf("%d%d", &n, &s))
{
memset(d, , sizeof(d));
d[n][s] = ;
for(i = n; i >= ; i--)
for(j = s; j >= ; j--)
{
if(i==n && j==s) continue;
d[i][j] = ( + d[i][j+]*(i*1.0/n*(s-j)*1.0/s)+
d[i+][j]*(j*1.0/s*(n-i)*1.0/n)+
d[i+][j+]*((n-i)*1.0/n*(s-j)*1.0/s))*1.0/(1.0-(i*j)*1.0/(n*s));
//上面的式子是三种情况 和 最后乘的是为了达到i、j加一天的概率。
//上面的递推式子简洁一点化简完是这样的:
//dp[i][j]=(i*(s-j)*dp[i][j+1]+(n-i)*j*dp[i+1][j]+(n-i)*(s-j)*dp[i+1][j+1]+n*s)/(n*s-i*j);
}
printf("%.4f\n", d[][]);
}
return ;
}

贴一个很好的概率dp的分析(转载的链接):

近年的acm竞赛中,数学期望问题常有涉及,在以前也常让本人感到很头疼,近来突然开窍,掌握了基本的分析方法,希望对大家有帮助。写得浅薄,可能数学上不够严谨,只供理解。

首先,来看下期望有啥基本的公式。

对离散型随机变量x,其概率为p,有

对随机变量A、B,有 

第二条式子是今天的主角,他表明了期望有线性的性质,简单理解就是期望之间可根据关系,简单运算(不严谨的理解)。 这就为我们解决一个期望问题,不断转化为解决另外的期望问题,最终转化到一个已知的期望上。

举一个求期望最简单的例子,见下图。

假设有个人在 1号节点处,每一分钟他会缘着边随机走到一个节点或者在原地停留,问他走到4号节点需要平均几分钟?

这是个简单的期望问题,我们用Ei(i=1,2,3,4) 表示从i号节点走到4号节点的数学期望值。根据题意对1号节点有

E1=(1/3)*E1+(1/3)*E2+(1/3)*E3+1 ①

表示 他下一分钟可以走到2或者3或在原地1,每个可能概率是1/3 ,注意是下一分钟,故要加上1.

同理我们对节点2,3同样可以列出

E2=(1/3)*E1+(1/3)*E2+(1/3)*E4+1 ②

E3=(1/3)*E1+(1/3)*E3+(1/3)*E4+1 ③

那E4等于多少呢? 很明显E4=0 ④,因为他就是要到点4

这样上面1234式其实就是组成了一组方程组,解方程组就可得出E1!!,用高斯消元,复杂度是O(n^3)

从上述例子,我们可总结出如何解决期望类问题,根据题意,表示出各个状态的期望(上例的Ei,1234),根据概率公式,列出期望之间的方程,解方程即可。

下面看用上述思路如何解决一道题(poj2096)

原题见附件1。

题意简述: 一个人受雇于某公司要找出某个软件的bugs和subcomponents,这个软件一共有n个bugs和s个subcomponents,每次他都能同时随机发现1个bug和1个subcomponent,问他找到所有的bugs和subcomponents的期望次数。

我们用E(i,j)表示他找到了i个bugs和j个subcomponents,离找到n个bugs和s个subcomponents还需要的期望次数,这样要求的就是E(0,0),而E(n,s)=0,对任意的E(i,j),1次查找4种情况,没发现任何新的bugs和subcomponents,发现一个新的bug,发现一个新的subcomponent,同时发现一个新的bug和subcomponent,用概率公式可得:

E(i,j)=1+(i*j/n/s)*E(i,j)+(i*(s-j)/n/s)E(i,j+1)+

((n-i)*j/n/s)*E(i+1,j)+(n-i)*(s-j)/n/s*E(i+1,j+1);

这样根据边界就可解出所有的E(i,j),注意因为当我们找到n个bugs和s个subcomponents就结束,对i>n||j>s均无解的情况,并非期望是0.(数学上常见问题,0和不存在的区别)

那这题是否也是要用高斯消元呢? 用高斯消元得话复杂度是O(n^3),达到10^18 根本是不可解的!!

但其实,注意观察方程,当我们要解E(i,j)的话就需要E(i+1,j),E(I,j+1),E(i+1,j+1), 一开始已知E(n,s),那其实只要我们从高往低一个个解出I,j就可以了! 即可根据递推式解出所有的E(I,j) 复杂度是O(n),10^6 ,完美解决。程序见附件2

从上面这道题,我们再次看到了解决期望问题的思路,而且是用到了递推解决问题,其实可递推的原因,当我们把各个状态当成是一个个节点时,概率关系为有向边,我们可看到,可递推的问题其实就是这个关系图是无环的!!那必须要用方程组解决的问题其实就是存在环!!!! 而且我还要指出的是用高斯消元的时候,要注意误差的问题,最好把式子适当的增大,避免解小数,否则误差太大,估计也会卡题。

再加一个题,今天同学问我的笔试题:

 #include<iostream>
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<cmath>
#include<algorithm>
using namespace std;
const int maxn = 1e5 + ;
double d[maxn]; int main()
{
int n, i;
while(cin>>n)
{
d[n+] = ;
for(i = n; i >= ; i--)
{
double p1, p2;
p1 = double(i)/double(n);
p2 = 1.0 - p1;
d[i] = (p1*(d[i+]+1.0)+p2)/(1.0-p2);
}
printf("%.4lf\n", d[]);
}
return ;
}
/*今天同学问我的一个笔试题,题意:一个人和n个人相亲,随机有可能重复相亲,
问把这n个人相亲完的次数? d[i] = d[i+1]*p1 + d[i]*(1-p1) + 1;
d[i]为从i人到n人的期望,p1为和没相过亲的人相的概率。
加一天d[i]有p1概率变为d[i+1],有(1-p1)概率还是d[i];
*/
注意:这本来应该是初始化d[n] = 0,输出d[0]。因为n的状态到n的状态需要0次。
但是如果这么算的话,就有i=0的时候,做分母不能算,所有就是初始化了d[n+1],输出d[1]。

poj 2096 Collecting Bugs (概率dp 天数期望)的更多相关文章

  1. Poj 2096 Collecting Bugs (概率DP求期望)

    C - Collecting Bugs Time Limit:10000MS     Memory Limit:64000KB     64bit IO Format:%I64d & %I64 ...

  2. POJ 2096 Collecting Bugs (概率DP,求期望)

    Ivan is fond of collecting. Unlike other people who collect post stamps, coins or other material stu ...

  3. POJ 2096 Collecting Bugs (概率DP)

    题意:给定 n 类bug,和 s 个子系统,每天可以找出一个bug,求找出 n 类型的bug,并且 s 个都至少有一个的期望是多少. 析:应该是一个很简单的概率DP,dp[i][j] 表示已经从 j ...

  4. poj 2096 Collecting Bugs 概率dp 入门经典 难度:1

    Collecting Bugs Time Limit: 10000MS   Memory Limit: 64000K Total Submissions: 2745   Accepted: 1345 ...

  5. POJ2096 Collecting Bugs(概率DP,求期望)

    Collecting Bugs Ivan is fond of collecting. Unlike other people who collect post stamps, coins or ot ...

  6. poj 2096 Collecting Bugs - 概率与期望 - 动态规划

    Ivan is fond of collecting. Unlike other people who collect post stamps, coins or other material stu ...

  7. POJ 2096 Collecting Bugs 期望dp

    题目链接: http://poj.org/problem?id=2096 Collecting Bugs Time Limit: 10000MSMemory Limit: 64000K 问题描述 Iv ...

  8. poj 2096 Collecting Bugs(期望 dp 概率 推导 分类讨论)

    Description Ivan is fond of collecting. Unlike other people who collect post stamps, coins or other ...

  9. poj 2096 Collecting Bugs 【概率DP】【逆向递推求期望】

    Collecting Bugs Time Limit: 10000MS   Memory Limit: 64000K Total Submissions: 3523   Accepted: 1740 ...

随机推荐

  1. C51关键字

    C51 中的关键字 关键字 用途 说明 auto 存储种类说明 用以说明局部变量,缺省值为此 break 程序语句 退出最内层循环 case 程序语句 Switch语句中的选择项 char 数据类型说 ...

  2. IE8下兼容rgba颜色的半透明背景

    在工作中做一个图片半透明遮罩时发现在IE8下不兼容 一查再知道IE8不支持rgba颜色,再搜搜兼容性方法,没想到这么快就解决了. 先说说rgba的含义: r代表red,g代表green,b代表blue ...

  3. 【高可用HA】Apache (1) —— Mac下安装Apache Httpd到自定义路径(非/etc/apache2)

    Mac下安装Apache Httpd httpd版本: httpd-2.4.17 参考来源: Tomcat Clustering - A Step By Step Guide Apache HTTP ...

  4. Unity bundle的制作和使用

    原地址:http://unity3d.9ria.com/?p=2863 Unity有个很好的功能,大致是很多专注于PC的engine没有提供的(因为没有必要),就是能加载主包外的资源,这个主包外的资源 ...

  5. Sqli-labs less 28

    Less-28 本关考察内容与27关没有太大的差距,我们直接给出一个payload: http://127.0.0.1/sqllib/Less-28/?id=100')union%a0select(1 ...

  6. Codeforces 452E Three Strings(后缀自动机)

    上学期很认真地学了一些字符串的常用工具,各种 suffix structre,但是其实对后缀自动机这个部分是理解地不太透彻的,以致于看了师兄A这题的代码后,我完全看不懂,于是乎重新看回一些学习后缀自动 ...

  7. POJ 1504

    #include<iostream> using namespace std; int main() { int num; cin>>num; while(num--){ in ...

  8. App接口设计

    关于APP接口设计 http://blog.csdn.net/gebitan505/article/details/37924711/

  9. 2013 ACM/ICPC Asia Regional Changsha Online G Goldbach

    比赛的时候,被题目误导了,题目最后说结果可能很大,要取模,那时就想直接求会TLE的!!! 赛后才知道,坑啊………… 代码如下: #include<iostream> #include< ...

  10. lintcode:两个数组的交

    题目 返回两个数组的交 样例 nums1 = [1, 2, 2, 1], nums2 = [2, 2], 返回 [2]. 解题 排序后,两指针找相等元素,注意要去除相同的元素 public class ...