题目链接

题意:

一个人受雇于某公司要找出某个软件的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. spring.net +dapper 打造简易的DataAccess 工具类.

    public class DBUtil { /// <summary> /// 数据库连接字符串 /// </summary> private static string Da ...

  2. extjs4 与 kindeditor

    <link rel="stylesheet" href="<?php echo Yii::app()->request->baseUrl;?> ...

  3. [工作积累] Android: Hide Navigation bar 隐藏导航条

    https://developer.android.com/training/system-ui/navigation.html View decorView = getWindow().getDec ...

  4. PowerDesigner(二)-项目和框架矩阵(转)

    项目和框架矩阵 项目是PowerDesigner 15的新概念,通过项目系统分析/设计人员可以对模型以及各类文档进行分组.项目也可以包含框架矩阵,以表格的形式体现各个模型之间的关系. 项目和框架矩阵解 ...

  5. php __FILE__,__CLASS__等魔术变量,及实例(转)

    今天看到一个魔术变量,是以前没见过的,__DIR__,我查了查,发现原来是php5.3新增的,顺便举几个例子,解释一下php的魔术变量 1,__FILE__ 文件的完整路径和文件名.如果用在被包含文件 ...

  6. ios 5

    1.屏幕尺寸568×2/320×2  需要一张568h@2x.png的图片. 2.iOS5不支持udid,用uuid替代,取得uuid方法: -(NSString*) uuid { CFUUIDRef ...

  7. CSS 类名的单词连字符:下划线还是连接符?

    本文的部分内容整理自我对此问题的解答: 命名 CSS 的类或 ID 时单词间如何连接? - 知乎 问题 CSS 类或 ID 命名时单词间连接通常有这几种写法: 驼峰式: solutionTitle.s ...

  8. 使用CSS3实现3D图片滑块效果

    使用 CSS3 的3D变换特性,我们可以通过让元素在三维空间中变换来实现一些新奇的效果. 这篇文章分享的这款 jQuery 立体图片滑块插件,利用了 3D transforms(变换)属性来实现多种不 ...

  9. Keil RTX systick 初始化

    在STM32F215上移植Keil的RTX操作系统,随便设置下就能好使,但是当我想知道systick到底是怎么设置的时候,就得翻翻代码了,原来在 rt_HAL_CM.h中以一个内联函数的形式定义的 _ ...

  10. Chapter 4

    1.Python中有四种函数:全局函数,局部函数,lambda函数,方法.其中全局函数与局部函数对比理解,局部函数就是定义在某函数之内的函数,否则就是全局函数,lambda函数就是表达式,方法就跟对象 ...