递归算法实例应用(四)

简介: 递归算法实例应用(四):(POJ 4017)爬楼梯、(POJ 1664)放苹果

递归算法实例应用(四)

爬楼梯 (POJ 4017)

Description

树老师爬楼梯,他可以每次走1级或者2级,输入楼梯的级数,求不同的走法数
例如:楼梯一共有3级,他可以每次都走一级,或者第一次走一级,第二次走两级
也可以第一次走两级,第二次走一级,一共3种方法。

Input

输入包含若干行,每行包含一个正整数N,代表楼梯级数,1 <= N <= 30

Output

不同的走法数,每一行输入对应一行输出

Sample Input

5
8
10    

Sample Output

8
34
89




算法思想:

首先,假设n充分大时,从分析第一步应如何走开始,第一步可以分为两种情况,即上一层台阶和上两层台阶;接下来考虑第二步应该怎么走,第二步与第一步一样也是可以分为两种情况,但是剩余台阶数相比于第一步减少了一层或两层;第三步同理,直至某一步时,使得台阶正好走完。

从上面分析可知,随着每一步的走法确定之后,问题规模的台阶数就会变少一层或两层。所以该问题就是一个非常明显的用递归将问题规模分解为规模更小的子问题进行求解的问题。

那么该问题的递归公式可以表示为:

n级台阶的走法 = 先走1级后n-1阶台阶的走法 + 先走2级后n-2级台阶的走法

接下来考虑递归的终止条件,输入数据规模为1 <= N <= 30,通过递归公式的逐层递归推导,可以发现几种不同的终止情况

f(n)=0,n<0

f(n)=1,n=0

对于每一个n,要么由上一层的N-1而来,要么由N-2而来:

  • 当n<0时,说明上一层的N-1或N-2的走法不成立,所以应返回0,表明不可行,即N-1或N-2有0种走法。
  • 当n=1时,说明上一层N-1或N-2走法使得仅剩下一层台阶要走,所以应仅有一种走法,即一步一个台阶。

f(n)=1,n=1
f(n)=1,n=0

同理,对于每一个n,要么由上一层的N-1而来,要么由N-2而来:

  • 当n=0时,说明上一层的N-1或N-2的走法正好走完整个楼梯,所以该层已经不需要走了,故应返回0。
  • 当n=1时,说明上一层N-1或N-2走法使得仅剩下一层台阶要走,所以应仅有一种走法,即一步一个台阶。

f(n)=1,n=1
f(n)=2,n=2

同理,对于每一个n,要么由上一层的N-1而来,要么由N-2而来:

  • 当n=1时,说明上一层N-1或N-2走法使得仅剩下一层台阶要走,所以应仅有一种走法,即一步一个台阶。
  • 当n=2时,说明上一层N-1或N-2走法使得仅剩下两层台阶要走,所以应仅有两种走法,即一步一个台阶,或一步两个台阶。

以上便列举了三种不同的终止条件,读者选择一种作为函数终止条件即可。对于终止条件的分析,应从解的递归函数出发,分析其可能终止或异常的几种状态,罗列下终止状态后,判断是否涵盖在此递归函数中所有可能出现的终止或异常状态。因为算法应涵盖在题设的输入条件下,所有可能的解的情况,保证函数的健壮性。




代码逻辑:

本题的递归递归函数和终止条件均较为简单,所以代码逻辑不再赘述。




代码整合:

int main() {
    //爬楼梯
    int n;
    while (scanf("%d", &n)) {//读入每一个输入数据
        printf("%d\n", Stairs(n));//每读入一个数据就输出该问题规模下的解
    }
    return 0;
}

int Stairs(int n) {
    //终止条件
    if (n < 0)
        return 0;
    if (n == 0)
        return 1;

    //递归公式
    return Stairs(n - 1) + Stairs(n - 2);
}




放苹果 (POJ 1664)

Description

把M个同样的苹果放在N个同样的盘子里,允许有的盘子空着不放,问共有多少种不同的分法?(用K表示)5,1,1和1,5,1 是同一种分法。

Input

第一行是测试数据的数目t(0 <= t <= 20)。以下每行均包含二个整数M和N,以空格分开。1<=M,N<=10。

Output

对输入的每组数据M和N,用一行输出相应的K。

Sample Input

1
7 3

Sample Output

8




算法思想:

由题设输入可分为两种情况,

  1. 盘子数n > 苹果数m,此时必定至少有n-m个盘子为空,所以问题规模此时就变为将n个苹果放在n个盘子里。
  2. 盘子数n ≤ 苹果数m,此时苹果有两种放法:

    • 有空盘放法

      • 若有一个空盘,则问题规模变为,将m个苹果放在n-1个盘子里
      • 若有两个空盘,则问题规模变为,将m个苹果放在n-2个盘子里
      • 若有..个空盘,则问题规模变为,将m个苹果放在...个盘子里
      • 若有n-1个空盘,则问题规模变为,将m个苹果放在1个盘子里
    • 无空盘放法

      • 把n个盘子各放一个苹果,再将剩余的m-n个苹果放在n个盘子里,问题规模再次缩减,此时剩余的m-n个苹果可以在n个盘子里随便放。
    • 所以,综上当盘子数≤苹果数时,放法个数为又空盘放法与无空盘放法之和。

从以上分析可知,该问题也是一个用递归将问题规模分解为规模更小的子问题进行求解的问题。

若用f(m,n)表示m个苹果放在n个盘子里的放法,那么该问题的递归公式可以表示为:

$$ f(m,n)= \begin{cases} f(m,m),& n>m \\ \\ f(m,n-1)+f(m-n,n),& n\le m \\ \end{cases}\tag1 $$

接下来考虑递归的终止条件,通过递归公式的逐层递归推导,可以发现几种不同的终止情况

$$ f(m,n)= \begin{cases} 1,& m=0 \\ \\ 0,& n=0 \\ \end{cases}\tag2 $$

即,当盘子数为0时,没有放法可以盘子题设要求,故解为0,当苹果数为0时,只有每个盘子都不放苹果这一种解法。

而且苹果为0时的边界优先级较盘子为0时的边界判定更高!




代码逻辑:

本题的递归递归函数和终止条件均较为简单,所以代码逻辑不再赘述。




代码整合:

int main() {
    //放苹果
    int m, n, count;
    scanf("%d", &count);
    while (count--) {
        scanf("%d%d", &m, &n);
        printf("%d\n", SetApple(m, n));//每读入一组数据就输出该问题规模下的解
    }
    return 0;
}

int SetApple(int m, int n) {
    if (n > m) {
        return SetApple(m, m);//盘子数大于苹果数,简化问题规模
    }
    if (m == 0) {//苹果数为0,只有一种全不放的放法,到达递归终止点
        return 1;
    }
    if (n == 0) {//盘子数为0,此时无解,到达递归终止点
        return 0;
    }
    //当盘子数≤苹果数时,为有空盘子放法与无空盘子放法之和
    return SetApple(m, n - 1) + SetApple(m - n, n);
}


By Ss1Two 2023/01/17

目录
相关文章
|
2月前
|
存储 算法 Java
解析HashSet的工作原理,揭示Set如何利用哈希算法和equals()方法确保元素唯一性,并通过示例代码展示了其“无重复”特性的具体应用
在Java中,Set接口以其独特的“无重复”特性脱颖而出。本文通过解析HashSet的工作原理,揭示Set如何利用哈希算法和equals()方法确保元素唯一性,并通过示例代码展示了其“无重复”特性的具体应用。
54 3
|
2月前
|
机器学习/深度学习 人工智能 自然语言处理
深度学习中的优化算法及其应用
【10月更文挑战第8天】 本文将探讨深度学习中常用的优化算法,包括梯度下降法、Adam和RMSProp等,介绍这些算法的基本原理与应用场景。通过实例分析,帮助读者更好地理解和应用这些优化算法,提高深度学习模型的训练效率与性能。
193 63
|
21天前
|
机器学习/深度学习 人工智能 算法
探索人工智能中的强化学习:原理、算法与应用
探索人工智能中的强化学习:原理、算法与应用
|
20天前
|
机器学习/深度学习 算法 数据挖掘
C语言在机器学习中的应用及其重要性。C语言以其高效性、灵活性和可移植性,适合开发高性能的机器学习算法,尤其在底层算法实现、嵌入式系统和高性能计算中表现突出
本文探讨了C语言在机器学习中的应用及其重要性。C语言以其高效性、灵活性和可移植性,适合开发高性能的机器学习算法,尤其在底层算法实现、嵌入式系统和高性能计算中表现突出。文章还介绍了C语言在知名机器学习库中的作用,以及与Python等语言结合使用的案例,展望了其未来发展的挑战与机遇。
39 1
|
20天前
|
并行计算 算法 测试技术
C语言因高效灵活被广泛应用于软件开发。本文探讨了优化C语言程序性能的策略,涵盖算法优化、代码结构优化、内存管理优化、编译器优化、数据结构优化、并行计算优化及性能测试与分析七个方面
C语言因高效灵活被广泛应用于软件开发。本文探讨了优化C语言程序性能的策略,涵盖算法优化、代码结构优化、内存管理优化、编译器优化、数据结构优化、并行计算优化及性能测试与分析七个方面,旨在通过综合策略提升程序性能,满足实际需求。
49 1
|
1月前
|
缓存 算法 网络协议
OSPF的路由计算算法:原理与应用
OSPF的路由计算算法:原理与应用
42 4
|
27天前
|
机器学习/深度学习 监控 算法
基于反光衣和检测算法的应用探索
本文探讨了利用机器学习和计算机视觉技术进行反光衣检测的方法,涵盖图像预处理、目标检测与分类、特征提取等关键技术。通过YOLOv5等模型的训练与优化,展示了实现高效反光衣识别的完整流程,旨在提升智能检测系统的性能,应用于交通安全、工地监控等领域。
|
1月前
|
存储 算法 网络协议
OSPF的SPF算法介绍:原理、实现与应用
OSPF的SPF算法介绍:原理、实现与应用
76 3
|
1月前
|
机器学习/深度学习 JSON 算法
二叉树遍历算法的应用场景有哪些?
【10月更文挑战第29天】二叉树遍历算法作为一种基础而重要的算法,在许多领域都有着不可或缺的应用,它为解决各种复杂的问题提供了有效的手段和思路。随着计算机科学的不断发展,二叉树遍历算法也在不断地被优化和扩展,以适应新的应用场景和需求。
40 0
|
21天前
|
机器学习/深度学习 人工智能 算法
探索人工智能中的强化学习:原理、算法及应用
探索人工智能中的强化学习:原理、算法及应用
下一篇
DataWorks