poj2096 Collecting Bugs

传送门:http://poj.org/problem?id=2096

【题解】

看到有人在uoj群上问这个……就去看了看…

顺便复习下概率dp

$f_{i,j}$表示这个人已经找出了$i$种系统的bug,和$j$种bug的期望步数。

每次有4种转移:

1. 发现了新的bug种类,属于新的系统,那么是$f_{i+1, j+1}$,概率是$i/s * j/n$,设两者相乘为$a$;

2. 发现了新的bug种类,属于原有系统,那么是$f_{i, j+1}$,概率是$(s-i)/s * (n-j)/n$,设两者相乘为$b$;

3. 发现了原有bug种类,属于新的系统,那么是$f_{i+1, j}$,概率是$i/s * (n-j)/n$,设两者相乘为$c$;

4. 发现了原有bug种类,属于原有系统,那么是$f_{i,j}$,概率是$(n-i)/s * (n-j)/n$,设两者相乘为$d$

所以$f_{i,j} = 1 + a + b + c + d$,把$f_{i,j}$移项即可得到转移式子。

答案为$f_{0,0}$,这是经典的从后往前推概率dp。复杂度$O(ns)$。

# include <stdio.h>
# include <string.h>
# include <iostream>
# include <algorithm>
// # include <bits/stdc++.h>

using namespace std;

typedef long long ll;
typedef long double ld;
typedef unsigned long long ull;
const int M = 1e3 + 10;
const int mod = 1e9+7;

int n, s;
ld f[M][M];

inline void prtld(const ld& x) {
    printf("%.4lf\n", (double)x);
}

// 发现了i个系统的bug,j种bug的方案数的期望 
// 1. 发现了新的bug种类,属于新的系统
// 2. 发现了新的bug种类,属于原有系统
// 3. 发现了原有bug种类,属于新的系统
// 4. 发现了原有bug种类,属于原有系统 

int main() {
    cin >> n >> s;  
    for (int i=s; ~i; --i)
        for (int j=n; ~j; --j) {
            if(i == s && j == n) continue;
            f[i][j] = (f[i+1][j+1] * (s-i) * (n-j) + f[i+1][j] * (s-i) * j + f[i][j+1] * i * (n-j) + n * s) / (n * s - i * j);
        }
    prtld(f[0][0]); 
    return 0;
}
View Code

 

posted @ 2017-07-15 21:00  Galaxies  阅读(226)  评论(0编辑  收藏  举报