码迷,mamicode.com
首页 > 其他好文 > 详细

概率dp小结

时间:2015-08-08 07:57:13      阅读:78      评论:0      收藏:0      [点我收藏+]

标签:

好久之前学过,记得是一次亚洲区的前几天看了看概率dp,然后亚洲区就出了一道概率dp,当时虽然做上了,但是感觉有很多地方没懂,今天起早温习了一下,觉得很多地方茅塞顿开,果然学习的话早上效果最好了。

首先来看一道最基础概率dp

题意是,有一个软件,有s个子系统,会产生n种bug。 
某个程序员一天能发现一个bug,这个bug是这n种bug中的一种,然后发生在某个子系统中。 
问,找到所有的n种bug,且每个子系统都找到bug,这样所要的天数,的期望。

期望,可以分解成多个子期望的加权和,权为子期望发生的概率 
所以: 我首先想到了一个这样的公式dp[x][y] = dp[x][y]*p1+dp[x-1][y-1]*p2+dp[x][y-1]*p3+dp[x-1][y]*p4

dp[x][y]代表已经有x种bug并且有y个系统至少有一个bug的期望值

我们知道他是从自身以及他的前几种状态推导过来,乍一看这个公式应该是对的,但是dp[n][m]会无穷大,因为他的期望是没有停止状态的,也就是题意要求的应该是到达n,m状态时停止。

那么我们又可以从倒推的角度去考虑这个问题,dp[x][y]表示的是已经有x种bug并且有y个系统至少有一种bug的时候还需要多少步能够到达dp[n][m]的状态。

那么公式又变成了这样dp[x][y] = dp[x+1][y+1]*p1+dp[x+1][y]*p2+dp[x][y+1]*p3+dp[x][y]*p4+1

也就是dp[x][y] = dp[x+1][y+1] *(n-x)*(m-y)/n/m+dp[x+1][y]*(n-x)*y/n/m+dp[x][y+1]*x*(m-y)/n/m+dp[x][y]*x*y/n/m+1

将dp[x][y]合并得dp[x][y](1-x*y/n/m) = dp[x+1][y+1] *(n-x)*(m-y)/n/m+dp[x+1][y]*(n-x)*y/n/m+dp[x][y+1]*x*(m-y)/n/m+1

1.poj2096,就是上面的题

技术分享
#include<stdio.h>
#include<string.h>
#include<iostream>
using namespace std;
double dp[1004][1004];
int main(){
    int n, m;
    scanf("%d%d", &n, &m);
        for(int i =0 ;i <= n+1; i++){
            for(int k = 0; k <= m+1; k++){
                dp[i][k]= 0;
            }
        }
        for(int x = n; x >= 0; x--){
            for(int y = m; y >=0; y--){
                if(x == n && y ==m)dp[x][y] = 0;
                else
                dp[x][y]= (1+dp[x+1][y+1] *(n-x)*(m-y)/n/m+dp[x+1][y]*(n-x)*y/n/m+dp[x][y+1]*x*(m-y)/n/m)/(1.0-1.0*x*y/n/m);
            }
        }
        printf("%.4f\n", dp[0][0]);
}
View Code

 

概率dp小结

标签:

原文地址:http://www.cnblogs.com/icodefive/p/4712477.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!