POJ2096 Collecting Bugs
Posted ywjblog
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了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<iostream> 2 #include<iomanip> 3 #include<cstdio> 4 #include<ctime> 5 #include<cstring> 6 #include<cstdlib> 7 #include<algorithm> 8 #include<cmath> 9 using namespace std; 10 const int maxn = 1010; 11 int n, s; 12 double f[maxn][maxn], p1, p2, p3, p4; 13 14 int main() { 15 cin >> n >> s; 16 f[n][s] = 0; 17 memset(f, 0, sizeof(f)); 18 for(int i = n; i >= 0; --i) 19 for(int j = s; j >= 0; --j) { 20 if(i == n && j == s) continue; 21 p1 = 1.0 * i * (s - j) / (n * s); 22 p2 = 1.0 * (n - i) * j / (n * s); 23 p3 = 1.0 * i * j / (n * s); 24 p4 = 1.0 * (n - i) * (s - j) / (n * s); 25 f[i][j] = (p1 * f[i][j + 1] + p2 * f[i + 1][j] + p4 * f[i + 1][j + 1] + 1) / (1 - p3); 26 } 27 printf("%.4lf ", f[0][0]); 28 return 0; 29 }
以上是关于POJ2096 Collecting Bugs的主要内容,如果未能解决你的问题,请参考以下文章