题目描述:
近日,项目中偶遇一个有趣的题目,感慨多多,备忘之。抽象出来,大致是:
桌上一共有100个饺子,其中有10个饺子包了硬币,问:连续吃到硬币的期望次数是多少次?
首先,定义一下这里的连续,如果我们将吃饺子的顺序抽象为一个100位的二进制数。并且吃到饺子表示为1,没吃到则为0,那么:
- 如果一次和第二次吃到,那么可表示为: 110.....,那么这里的连续吃到的次数为1.
- 如果数字为: ...1111.... ,那么这里连续的4个1表示3次连续,也就是说只要连续,就算1次。
期望次数,也就是说我们需要算出0个连续,1个连续,....9个连续。这10个计数。
注:这里的连续其实就是取决于当前位置的前一个位置的状态即可。因此可以用DP来解决。
此题目是一个数数的问题,显然可以使用DP来进行求解。
global[i][j][k] : 表示前i个饺子中,已经吃到了j个硬币,并且连续的次数为k。
local[i][j][k] : 表示前i个饺子中,吃到了j个硬币,并且第k次连续发生在第i个位置上。(也就是说第i-1次吃到的也是饺子)。并且连续的次数为k。
-
local[i][j][k] = local[i-1][j-1][k-1] + global[i-3][j-2][k-1]
-
global[i][j][k] = local[i][j][k] + global[i-2][j][k] + global[i-2][j-1][k] + local[i-3][j-2][k-1] + global[i-3][j-1][k]
显然上式以最后一次是否连续作为子问题是不明智的,递推关系式太过复杂。
下面从另一个角度来分析:
以最后两位的状态来决定:
- 11 : 那就是连续一次,
- 10 , 01, 00 , 都没有连续,子问题直接递推即可。
因此,定义如下子问题:
f[i][j][k][0/1] : 表示前i个饺子中,吃到了j个硬币,并且有k个连续。且最后一个是0/1的次数。
那么我们要求的就是: f[100][10][k][0] + f[100][10][k][1]; k = {1,2,3,...,9}
注意:这里的最后一维其实就是一个0/1的记录,当然你也可以使用两个三维数组来表示。Python代码实现如下: