递归算法(三)——多项分布问题

时间:2024-07-18 21:35:02

问题

一个枪手打靶,靶从外向内有1-10分(考虑脱靶得0分),打十枪,求枪手最后得90分的概率。

解决思路

一、穷举

考虑10重for循环,累计十次得分和为90者,求得概率。该法通用性差,效率低,但容易想到。

二、映射

穷举共1110种可能,即(1e10)11。则考虑10进制数N,将其遍历,从0到1110-1,映射到11进制,解出每种可能下10次的得分,累计为90则计入。

注意:1110超出了int的范围,要考虑BigInteger。或者以字符串来计算大整数。

三、递归

从动态规划角度思考。

f(goal,left)表示,剩下还有left次机会,要打满goal分,返回可能种数。

显而易见,f(goal,left) = Sum{ f(goal',left-1) },其中goal-10<=goal'<=goal,这就是递归关系。

递归的出口为,left==1,即最后一次机会,必须打满goal分,故出口为return 0<=goal<=10。

有优化的可能吗?有,考虑:只有n次机会,但剩余n*10+1次是不可能的,超出上界。

故代码为:

int shot1(int count, int start, int end, int goal, int left) {
if ((goal > left * end) || (goal < left * start))
return 0;
if (left == 1)
return (goal >= start && goal <= end) ? 1 : 0;
int acc = 0;
for (int i = start; i <= end; i++)
acc += shot1(count, start, end, goal - i, left - 1);
return acc;
}

调用:

shot1(10, 0, 10, 90, 10);

相关文章