poj 2096 Collecting Bugs (期望dp)

题目链接:哆啦A梦传送门

题意:一个软件有s个系统,n个bug,每个系统有无数个bug,每天可以找出一个bug。

问:每个系统至少找出一个bug,并且所有种类的bug都找出来的期望天数?

算法合集之《浅析竞赛中一类数学期望问题的解决方法》

题解:

参考博客1:

参考博客2

期望dp。

我们设dp[i][j]表示已在j个系统中找出了i个bug,并且距离目标状态的期望天数。

很显然dp[i][j]可以有下面四个状态转移而来。

1,由dp[i][j]转移而来,意味着此次找到的bug既不是新的bug种类,也不是在新系统找出来的,那么此时由该状态转移而来的概率为: p1=i*j/n*s

2,由dp[i+1][j]转移而来,意味着此次找到的bug是新的bug种类,但不是在新系统找出来的,那么此时由该状态转移而来的概率

为:p2=(1-i/n)*(j/s)=(j*(n-i))/n*s

3,由dp[i][j+1]转移而来,意味着此次找的bug不是新的种类,但是在新系统找出来的,那么此时由该状态转移而来的概率

为:p3=(1-j/s)*(i/n)=(i*(s-j))/n*s

4,由dp[i+1][j+1]转移而来,意味着此次找到bug既是新的种类,也是在新系统找出来的,那么此时由该状态转移而来的概率

为:p4=(1-i/n)*(1-j/s)=(s-j)*(n-i)/n*s

 

期望可以分解成多个子期望的加权和,权为子期望发生的概率,即 E(aA+bB+...) = aE(A) + bE(B) +...

所以:

dp[i][j]=dp[i][j]*p1+dp[i+1][j]*p2+dp[i][j+1]*p3+dp[i+1][j+1]*p4+1。(后面+1,因为可以从四个其中一个转移而来,要花费一天的时间)

最后整理得: 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)

 

代码:

#include<cstdio>
#include<algorithm>
#include<cstring>

using namespace std;

const int N=1010;

double dp[N][N];
int main()
{
    int n,s;
    scanf("%d%d",&n,&s);

    dp[n][s]=0.0;

    for(int i=n;i>=0;i--)
    {
        for(int j=s;j>=0;j--)
        {
            if(i==n&&j==s) continue;

            dp[i][j]=(i*(s-j)*dp[i][j+1]+j*(n-i)*dp[i+1][j]+(n-i)*(s-j)*dp[i+1][j+1]+n*s)/(double)(n*s-i*j);
        }
    }

    printf("%.4f\n",dp[0][0]);
    return 0;
}

 

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值