概率与期望——【POJ2096】Collecting Bugs

文章讲述了如何使用动态规划解决一个概率问题,即在已知每个bug属于某个子系统的概率和分类概率的情况下,计算发现所有n种bug,每个s个子系统都出现bug的天数期望。通过状态设计、转移概率的计算和代码实现,详细解析了这个问题的解决方案。
摘要由CSDN通过智能技术生成

(一)题目

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

(二)状态设计 以及 答案分析

首先由上一道题的思路,我们很容易想到设dp[i][j]表示已经发现了i种错误、分别属于j个系统,还有几天到达n种bug,s个系统都发现bug的状态

然后我们发现dp[n][s](即n种bug,s个系统都发现bug)显然为0,答案也很明显在dp[0][0](什么bug都没发现)

(三)转移

1. 初步的错误思路

现在已经发现了i种bug,分属于j个系统,那么前一天一般情况下则可以有以下四种状态
{ d p [ i ] [ j ] (这一天发现了 b u g 但是没有影响进度) d p [ i + 1 ] [ j ] (这一天的 b u g 是一个新的种类) d p [ i ] [ j + 1 ] (这一天的 b u g 在一个新的系统) d p [ i + 1 ] [ j + 1 ] (这一天的 b u g 在一个新的系统且是一个新的种类) \begin{cases} dp[i][j](这一天发现了bug但是没有影响进度)\\ dp[i + 1][j](这一天的bug是一个新的种类)\\ dp[i][j + 1](这一天的bug在一个新的系统) \\ dp[i + 1][j + 1] (这一天的bug在一个新的系统且是一个新的种类) \end{cases} dp[i][j](这一天发现了bug但是没有影响进度)dp[i+1][j](这一天的bug是一个新的种类)dp[i][j+1](这一天的bug在一个新的系统)dp[i+1][j+1](这一天的bug在一个新的系统且是一个新的种类)
那么是不是就有 d p [ i ] [ j ] = d p [ i ] [ j ] + d p [ i ] [ j + 1 ] + d p [ i + 1 ] [ j ] + d p [ i + 1 ] [ j + 1 ] 4 + 1 dp[i][j] = \frac{dp[i][j] + dp[i][j + 1] + dp[i + 1][j] + dp[i + 1][j + 1]}{4}+ 1 dp[i][j]=4dp[i][j]+dp[i][j+1]+dp[i+1][j]+dp[i+1][j+1]+1了呢?

2.正确的思路

以上分析没有问题,但是忽略了一个重要的因素概率,很明显,这一天的bug在一个新的系统且是一个新的种类这一天的bug是一个新的种类的概率是不一样的嘛,怎么能用等概率事件的方法计算期望呢?而且以上四种状态中的一些可能不存在,比如(当 i + 1 > n i + 1 > n i+1>n j + 1 > s j + 1 > s j+1>s的情况)
所以在这个基础上,我们转移的时候还要给前驱状态乘上概率
形式化一点:
设以上四种事件发生的概率分别为 p 1 , p 2 , p 3 , p 4 , 则 d p [ i ] [ j ] = p 1 × d p [ i ] [ j ] + p 2 × d p [ i + 1 ] [ j ] + p 3 × d p [ i ] [ j + 1 ] + p 4 × d p [ i + 1 ] [ j ] + 1 设以上四种事件发生的概率分别为p_1,p_2,p_3,p_4,则 \\ dp[i][j] = p_1 \times dp[i][j] + p_2 \times dp[i + 1][j] + p_3 \times dp[i][j + 1] + p_4 \times dp[i + 1][j] + 1 \\ 设以上四种事件发生的概率分别为p1,p2,p3,p4,dp[i][j]=p1×dp[i][j]+p2×dp[i+1][j]+p3×dp[i][j+1]+p4×dp[i+1][j]+1
但是这样还是无法转移,因为无法从dp[i][j]这个位置状态转移到dp[i][j]这个未知状态
但是没有关系,移下项就好了嘛
d p [ i ] [ j ] − p 1 × d p [ i ] [ j ] = p 2 × d p [ i + 1 ] [ j ] + p 3 × d p [ i ] [ j + 1 ] + p 4 × d p [ i + 1 ] [ j + 1 ] + 1 d p [ i ] [ j ] = p 2 × d p [ i + 1 ] [ j ] + p 3 × d p [ i ] [ j + 1 ] + p 4 × d p [ i + 1 ] [ j + 1 ] + 1 1 − p 1 dp[i][j] - p_1 \times dp[i][j] = p_2 \times dp[i + 1][j] + p_3 \times dp[i][j + 1] + p_4 \times dp[i + 1][j + 1] + 1 \\ dp[i][j] = \frac{p_2 \times dp[i + 1][j] + p_3 \times dp[i][j + 1] + p_4 \times dp[i + 1][j + 1] + 1}{1 - p1} dp[i][j]p1×dp[i][j]=p2×dp[i+1][j]+p3×dp[i][j+1]+p4×dp[i+1][j+1]+1dp[i][j]=1p1p2×dp[i+1][j]+p3×dp[i][j+1]+p4×dp[i+1][j+1]+1

3.计算概率

现在只要求出 p 1 , p 2 , p 3 , p 4 p_1,p_2,p_3,p_4 p1,p2,p3,p4就好了
显然
p 1 = i n × j s p_1 = \frac{i}{n} \times \frac{j}{s} p1=ni×sj 即分步的乘法原理,在 n n n种可能的状态中有 i i i个被选过的满足,在 s s s个可能的系统中有 j j j个被选过的满足
p 2 = n − i n × j s p_2 = \frac{n - i}{n} \times \frac{j}{s} p2=nni×sj 同理,只不过在 n n n种可能的状态中有 n − i n - i ni个没有被选过的满足
p 3 = i n × s − j s p_3 = \frac{i}{n} \times \frac{s - j}{s} p3=ni×ssj同理,只不过在 s s s种可能的系统中有 s − j s - j sj个没有被选过的满足
p 4 = n − i n × s − j s p_4 = \frac{n - i}{n} \times \frac{s - j}{s} p4=nni×ssj乘法原理,在 n n n种可能的系统中有 n − i n - i ni个没有被选过的满足,在 s s s种可能的系统中有 s − j s - j sj个没有被选过的满足

这样就大功告成了
因为我们是已知最后状态dp[n][s] = 0,倒推dp[0][0]所写记忆化搜索方便些

(四)代码实现

思路前面讲的已经很清楚了,代码自己理解一下就好了

#include <bits/stdc++.h>
using namespace std;
const int N = 1000;
int n, s;
double dp[N + 5][N + 5];
double dfs(int i, int j) {
	if (i == n && j == s) return 0; // 到达目标状态
	if (dp[i][j] != 0) return dp[i][j];
	dp[i][j] = 1;
	if (i + 1 <= n) dp[i][j] += dfs(i + 1, j) * (n - i) * 1.0 * j / (n * s);
	if (j + 1 <= s) dp[i][j] += dfs(i, j + 1) * i * (s - j) / (1.0 * n * s);
	if (i + 1 <= n && j + 1 <= s) dp[i][j] += dfs(i + 1, j + 1) * (n - i) * 1.0 * (s - j) / (n * s);
	dp[i][j] /= (1.0 - i * j * 1.0 / (n * s));
	return dp[i][j];
}
int main() {
	scanf("%d%d", &n, &s);
	printf("%.4lf\n", dfs(0, 0));
	return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值