POJ 2096 Collecting Bugs 马尔可夫链 概率DP

来源:互联网 发布:百度地图网络异常 编辑:程序博客网 时间:2024/05/16 15:42

AC自动机的专题刷完了...开始刷概率了...


题目大意:

就是现在要从一个软件中找出bug, 这个软件有s个子模块,一共有n种bug,现在每天你可以找到一个bug, 这个bug属于任何一种bug和任何一个子模块都是等可能的, 问需要多少天使得每个子模块都有bug找到, 且一共找到n中不同的bug,求这个天数期望


大致思路:

大致思路见代码注释


代码如下:

Result  :  Accepted     Memory  :  8668 KB     Time  :  266 ms

/* * Author: Gatevin * Created Time:  2014/11/29 16:08:54 * File Name: Asuna.cpp *///submit language : G++#include<iostream>#include<sstream>#include<fstream>#include<vector>#include<list>#include<deque>#include<queue>#include<stack>#include<map>#include<set>#include<bitset>#include<algorithm>#include<cstdio>#include<cstdlib>#include<cstring>#include<cctype>#include<cmath>#include<ctime>#include<iomanip>using namespace std;const double eps(1e-8);typedef long long lint;double dp[1010][1010];/* * 用dp[i][j]表示当前找到了i种病毒,j个子模块已经找到了病毒之后,到达n中病毒,s个子模块的期望天数 * 那么对于点(i, j)可以到达状态 (i, j), (i + 1, j), (i, j + 1), (i + 1, j + 1), 当然到达状态需要在1~n, 1~s之间 * 因为从dp[0][0]出发一定会到达dp[1][1]也就是说i, j不可能只有1个为0, 同时i <= n, j <= s * 那么由于每次转移的代价都是1在上面的范围内 * dp[i][j] =   (i*j)/(n*s)*dp[i][j] + (n - i)*j/(n*s)*dp[i + 1][j]              + i*(s - j)/(n*s)*dp[i][j + 1] + (n - i)*(s - j)/(n*s)*dp[i + 1][j + 1] + 1(转移代价) * 对于i + 1, j + 1出界的情况就不用加上了,因为不存在这样的转移 * 而且显然有dp[n][s] = 0 * 用两层循环可以算出dp[1][1], 答案dp[0][0] = dp[1][1] + 1 */int main(){    int n,s;    while(~scanf("%d %d", &n, &s))    {        memset(dp, 0, sizeof(dp));        for(int i = n; i >= 1; i--)            for(int j = s; j >= 1; j--)            {                if(i == n && j == s) continue;                if(i < n) dp[i][j] += dp[i + 1][j]*(n - i)*j;                if(j < s) dp[i][j] += dp[i][j + 1]*i*(s - j);                if(i < n && j < s) dp[i][j] += dp[i + 1][j + 1]*(n - i)*(s - j);                dp[i][j] += n*s;                dp[i][j] /= (n*s - i*j);            }        printf("%.4f\n", dp[1][1] + 1);    }    return 0;}


0 0
原创粉丝点击