合规国际互联网加速 OSASE为企业客户提供高速稳定SD-WAN国际加速解决方案。 广告
所属专题:[组合数学](README.md);[动态规划](README.md) &emsp; ## 问题 回顾一下在[“兔子与递推关系”](FIB.md)问题中关于“斐波那契数”的定义,它满足递推式`$ F_n=F_{n-1}+F_{n-2} $`,假定每一对兔子在出生一个月后成熟,并从那时开始每个月繁殖新的一对兔子(一雄一雌)。 我们的目标是以某种方式改进这个递推关系,实现一个动态规划解决方案,以描述兔子将在固定的若干个月后去世的情况。下图描述了每只兔子存活三个月时的家族树(这意味着它们在去世前只繁殖两次)。(图片来源:[ROSALIND](http://rosalind.info/media/problems/hamm/)) ***** <div align="center"><img src="http://rosalind.info/media/problems/fibd/mortal_rabbit_tree.png"></div> <div align="center">斐波那契兔子的繁殖示意图,假设兔子寿命为三个月。</div> ***** **输入:** 两个正整数,`$ n \le 100 $`与`$ m \le 20 $`. **输出:** `$ n $`个月后总共存活的兔子对数,假设所有兔子寿命均为`$ m $`个月。 **样例数据:** ~~~ 6 3 ~~~ **样例输出:** ~~~ 4 ~~~ &emsp; ## 背景知识 该问题在传统的“斐波那契兔子”问题上加入了兔子寿命的限定,主要解决思路仍是动态规划,设定好状态转移方程(加上兔子死亡数一项)。详情请查阅ROSALIND网站上[关于该问题的背景说明](http://rosalind.info/problems/fibd/)。 &emsp; ## 解答 ``` def mortal_fib(n, m): """给定兔子寿命为m个月,计算n个月后兔子种群的对数""" if m==1: if n==1: result = 1 else: result = 0 elif m==2: result = 1 else: rabbits = [0, 1, 1] for i in range(3, m+1): rabbits.append(rabbits[-1]+rabbits[-2]) if n<=m: result = rabbits[n] else: rabbits.append(rabbits[-1]+rabbits[-2]-1) for i in range(m+2, n+1): rabbits.append(rabbits[-1]+rabbits[-2]-rabbits[-(m+1)]) result = rabbits[n] return result ## --main-- with open("rosalind_fibd.txt", 'r') as f1: n,m = map(int, f1.read().split()) result = mortal_fib(n, m) with open("rosalind_fibd_out.txt", 'w') as f2: f2.write(str(result)) ```