概率dp的边界处理 POJ 2096

题目地址:https://vjudge.net/problem/POJ-2096

说的是有n个bug,和s个系统。现在一个人一天能发现一个bug,它可能是任何一个系统中的,也可能会发现已经发现过的bug。

问,他发现全部n个bug,并且s个系统中都出现bug的天数的期望。

代码是借用kuangbin大神的:

 1 #include<stdio.h>
 2 #include<iostream>
 3 #include<algorithm>
 4 #include<string.h>
 5 using namespace std;
 6 const int MAXN=1010;
 7 double dp[MAXN][MAXN];
 8 
 9 int main()
10 {
11     int n,s;
12     while(scanf("%d%d",&n,&s)!=EOF)
13     {
14         dp[n][s]=0;
15         for(int i=n;i>=0;i--)
16           for(int j=s;j>=0;j--)
17           {
18               if(i==n&&j==s)continue;
19               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);
20           }
21         printf("%.4lf\n",dp[0][0]);//POJ上G++要改成%.4f
22     }
23     return 0;
24 }

关于转移方程,有什么不懂的可以移步   https://www.cnblogs.com/Paul-Guderian/p/7624039.html#undefined

没什么好说的,我这只弱鸡都能看懂。。。

 

 

但我觉得需要注意的地方是代码的第18行和19行,对边界的处理,可以说没有一点多余啊。。。

注意到dp过程是从 右下角(dp[n][s]) 开始的,决定当前位置的值是它右、下、以及右下位置的值

那么左边、上边的边界自然不用考虑,可能出现溢出的位置就剩下右边,下边,以及右下角。

我们注意到程序仅在第18行处理了右下角,是不是kuangbin大神漏掉了右边和下边的处理呢?

不,事实上右边和下边的处理在计算概率的时候就已经完成了!

就拿下边来说,注意到,当且仅当 i==n 时,访问 dp[i+1][j] 时会在下边越界。

但是,注意到与这一项相乘的概率恰好包括了 (n-i) 这一因子。

因此,越界访问得到的数据( dp[n+1][j] )并不会影响 dp[i][j] 的计算结果。

 

可能很简单。。。

但是对我这样的弱鸡来说,我觉得挺神奇的,求大犇们勿喷。。。

 

posted @ 2018-10-25 14:12  moonfair  阅读(294)  评论(0编辑  收藏  举报