Collecting Bugs POJ - 2096 期望dp

题意:有s个子结构,n种bug,每天都会发现一个bug,问发现n种bug,且每个子结构中都有bug的期望是多少

分析:
开始想状态是:
dp[i][j]:bug在i个子结构中,j种bug的期望天数,
然后由dp[i-1][j],dp[i-1][j-1],dp[i][j-1],dp[i][j]转移过来,
但是这四种状态转移到dp[i][j]的概率是一样的么?

比如:
假设 dp[i]:表示转移到i的期望步数。从1开始,那么dp[1]=1;
1可以转移到2,3,
2可以转移到3,4
3可以转移到4,5
这个时候我们要求dp[4],4可以由2,3转移过来,那么$dp[4]=1/2(dp[2]+dp[3])+1$;
这个时候上面的说法是错的,因为23转移到4的概率并不是相同的,因为2还会转移到3.倒着推的好处在哪呢,4转移到5,6,的概率是一样的。

通过上面的例子我们也清楚了不能直接顺着推(如果还是不相信的话,可以将这四个概率加起来,会发现比1小)。也不符合dp的后效性。
这个时候我们可以反着来推

dp[i][j]:bug在i个子结构,j种bug,离目标还需要的期望天数
可以转移到以下四个状态
dp[i+1][j]: 概率p1= (1i/s)(j/n)
dp[i][j+1]:概率p2= (i/s)(1j/n)
dp[i+1][j+1]:概率p3= (1i/s)(1j/n)
dp[i][j]:概率p4= i/sj/n

dp[s][n]=0;
dp[i][j]=(p1*dp[i+1][j]+p2*dp[i][j+1]+p3*dp[i+1][j+1]+1)/(1-p4);

using namespace std;
#define ll long long
#define mem(a,b) memset(a,b,sizeof(a))
const int maxn = 1e3+10;
double dp[maxn][maxn];
int main()
{
    int s,n;
    while(scanf("%d %d",&n,&s)!=EOF)
    {
        mem(dp,0);
        for(int i=s;i>=0;i--)
        {
            for(int j=n;j>=0;j--)
            {
                if(i==s&&j==n) continue;
                double p1=(double)(s-i)/s,p2=(double)(n-j)/n,p3=(double)i/s,p4=(double)j/n;
                dp[i][j]=((p1*p4)*dp[i+1][j]+(p3*p2)*dp[i][j+1]+(p1*p2)*dp[i+1][j+1]+1)/(1-p3*p4);
            }
        }
        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、付费专栏及课程。

余额充值