Rosalind: 兔子与递归

简介: 问题描述序列 指的是一组对象的集合,其中允许重复。序列分为有限序列和无限序列两种类型,我们通常用 表示序列中的第n个对象。递归其实就是当前的序列依赖于之前的序列。

问题描述

序列 指的是一组对象的集合,其中允许重复。序列分为有限序列和无限序列两种类型,我们通常用 a_n 表示序列中的第n个对象。

递归其实就是当前的序列依赖于之前的序列。最典型的案例就是兔子繁衍问题,假设一开始第一个月有1对兔子(A),到了第二个月这对兔子(A)性成熟,到了第三个月这对兔子(A)生出了一对兔子(B)。到了第四个月兔子(A)又生了一对兔子(D),之前刚的兔子(B)性成熟。到了第五个月,兔子(A)又生了兔子E,兔子(B)生出了兔子(F),而兔子(D)性成熟。

当然一图胜过千言万语,也就是下面这个情况

兔子繁衍图

这也就是斐波那契数列,公式为

F_n = F_{n-1} + F_{n-2}

现在,如果每个具有繁衍能力的兔子能够生出k对兔子,那么n个月后一共有多少对兔子?

结题思路

新的斐波那契数列如下:

F_n = F_{n-1} + K \times F_{n-2}

第一版递归代码如下:

#include <stdio.h>
#include <stdlib.h>

long int FIB(long int n, long int k)
{
    if (n == 1 || n == 2){
        return 1;
    } else{
        return FIB(n-1,k) + k * FIB(n-2, k);
    }

}

int main(int argc, char *argv[])
{
    if (argc != 3){
        printf("USAGE: ./FIB n k \n");
        return 1;
    }
    long int n = atoi(argv[1]);
    long int k = atoi(argv[2]);
    printf("month is %ld, %ld rabbit pairs per \n", n, k);
    long total = FIB(n,k);
    printf("The total number of rabbit is %ld \n", total);
    return 0;

}

注意,这个数字增长的很快,所以用了long int

上面的方法在month很大的时候时候,这些迭代算法的由于会反复求解一些重复的子问题,导致求解速度就会非常慢,比如求解第100个月会有多少个兔子,会需要很久很久。而且很容易导致栈溢出,解决方案就是**动态规划**dynamic programming

动态规划在查找有很多重叠子问题的情况的最优解时有效。它将问题重新组合成子问题。为了避免多次解决这些子问题,它们的结果都逐渐被计算并被保存,从简单的问题直到整个问题都被解决。因此,动态规划保存递归时的结果,因而不会在解决同样的问题时花费时间。

代码如下:

#include <stdio.h>
#include <stdlib.h>

int main(int argc, char *argv[])
{
    if (argc != 2){
        printf("USAGE: ./FIBv2 n k \n");
    }

    long int n = atoi(argv[1]);
    long int k = atoi(argv[2]);

    long int month[n-1];
    int i = 0;
    for (i = 0 ; i < n; i++){
        if ( i == 0 || i == 1){
            month[i] = 1;
        } else{
            month[i] = month[i-1] + k * month[i-2];
        }
    }

    printf("After %ld month, there are %ld rabbits\n", n, month[n-1]); 
   

    return 0;
}

这个代码在求解第100个月有多少兔子的时候,基本上是秒答。

目录
相关文章
|
2月前
lanqiao OJ 2097 青蛙过河
lanqiao OJ 2097 青蛙过河
12 0
|
7月前
|
机器学习/深度学习 索引
PTA-猴子选大王
程序模拟了猴子报数选猴王的过程,初始有N只猴子(N≤1000),从1号开始按1到3报数,报到3的猴子退出,直至只剩一只猴子,该猴子成为猴王。输入示例为11,输出示例为7。代码通过初始化猴子列表和当前报数索引,不断移除报数为3的猴子,最后返回剩余猴子的编号。
47 0
|
6月前
|
Java 程序员
程序员必知:URAL1513.LemonTale(简单的递推)
程序员必知:URAL1513.LemonTale(简单的递推)
29 0
|
7月前
|
机器学习/深度学习 算法 C++
【动态规划】C++算法:403.青蛙过河
【动态规划】C++算法:403.青蛙过河
华为机试HJ88:扑克牌大小
华为机试HJ88:扑克牌大小
112 0
PTA猴子选大王(约瑟夫环问题)
PTA猴子选大王(约瑟夫环问题)
129 1
|
存储 人工智能 算法
1732 51nod婚姻介绍所 后缀数组
1732 51nod婚姻介绍所 后缀数组
77 0
UPC-探险(线段树+二分)
UPC-探险(线段树+二分)
93 0
猴子吃桃子问题(循环、递归)
猴子吃桃子问题(循环、递归)
189 0
|
人工智能 Java
[HDU 7136] Jumping Monkey | 并查集 | 逆向思维
Jumping Monkey Time Limit: 8000/4000 MS (Java/Others) Memory Limit: 262144/262144 K (Java/Others) Total Submission(s): 747 Accepted Submission(s): 360
227 0
[HDU 7136] Jumping Monkey | 并查集 | 逆向思维